Fixed a nasty bug in Linux TLS initialization.
Improved thread/mutex debugging. git-svn-id: http://yate.null.ro/svn/yate/trunk@652 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
73e01366aa
commit
8faacfe499
|
@ -51,7 +51,8 @@ public:
|
||||||
: DataTranslator(sFormat,dFormat) { }
|
: DataTranslator(sFormat,dFormat) { }
|
||||||
virtual void Consume(const DataBlock& data, unsigned long tStamp)
|
virtual void Consume(const DataBlock& data, unsigned long tStamp)
|
||||||
{
|
{
|
||||||
ref();
|
if (!ref())
|
||||||
|
return;
|
||||||
if (getTransSource()) {
|
if (getTransSource()) {
|
||||||
DataBlock oblock;
|
DataBlock oblock;
|
||||||
if (oblock.convert(data, m_format, getTransSource()->getFormat())) {
|
if (oblock.convert(data, m_format, getTransSource()->getFormat())) {
|
||||||
|
@ -228,10 +229,9 @@ bool DataSource::attach(DataConsumer* consumer, bool override)
|
||||||
{
|
{
|
||||||
DDebug(DebugAll,"DataSource [%p] attaching consumer%s [%p]",
|
DDebug(DebugAll,"DataSource [%p] attaching consumer%s [%p]",
|
||||||
this,(override ? " as override" : ""),consumer);
|
this,(override ? " as override" : ""),consumer);
|
||||||
if (!consumer)
|
if (!(consumer && consumer->ref()))
|
||||||
return false;
|
return false;
|
||||||
Lock lock(m_mutex);
|
Lock lock(m_mutex);
|
||||||
consumer->ref();
|
|
||||||
if (override) {
|
if (override) {
|
||||||
// adjust timestamp for possible gaps in data
|
// adjust timestamp for possible gaps in data
|
||||||
int64_t dt = Time::now() - consumer->m_lastTsTime;
|
int64_t dt = Time::now() - consumer->m_lastTsTime;
|
||||||
|
@ -355,7 +355,8 @@ bool DataEndpoint::connect(DataEndpoint* peer)
|
||||||
return true;
|
return true;
|
||||||
DDebug(DebugInfo,"DataEndpoint '%s' connecting peer %p to [%p]",m_name.c_str(),peer,this);
|
DDebug(DebugInfo,"DataEndpoint '%s' connecting peer %p to [%p]",m_name.c_str(),peer,this);
|
||||||
|
|
||||||
ref();
|
if (!ref())
|
||||||
|
return false;
|
||||||
disconnect();
|
disconnect();
|
||||||
peer->ref();
|
peer->ref();
|
||||||
peer->disconnect();
|
peer->disconnect();
|
||||||
|
@ -471,9 +472,12 @@ void DataEndpoint::setConsumer(DataConsumer* consumer)
|
||||||
DataSource *source = m_peer ? m_peer->getSource() : 0;
|
DataSource *source = m_peer ? m_peer->getSource() : 0;
|
||||||
DataConsumer *temp = m_consumer;
|
DataConsumer *temp = m_consumer;
|
||||||
if (consumer) {
|
if (consumer) {
|
||||||
consumer->ref();
|
if (consumer->ref()) {
|
||||||
if (source)
|
if (source)
|
||||||
DataTranslator::attachChain(source,consumer);
|
DataTranslator::attachChain(source,consumer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
consumer = 0;
|
||||||
}
|
}
|
||||||
m_consumer = consumer;
|
m_consumer = consumer;
|
||||||
if (temp) {
|
if (temp) {
|
||||||
|
@ -490,9 +494,12 @@ void DataEndpoint::setPeerRecord(DataConsumer* consumer)
|
||||||
DataSource *source = m_peer ? m_peer->getSource() : 0;
|
DataSource *source = m_peer ? m_peer->getSource() : 0;
|
||||||
DataConsumer *temp = m_peerRecord;
|
DataConsumer *temp = m_peerRecord;
|
||||||
if (consumer) {
|
if (consumer) {
|
||||||
consumer->ref();
|
if (consumer->ref()) {
|
||||||
if (source)
|
if (source)
|
||||||
DataTranslator::attachChain(source,consumer);
|
DataTranslator::attachChain(source,consumer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
consumer = 0;
|
||||||
}
|
}
|
||||||
m_peerRecord = consumer;
|
m_peerRecord = consumer;
|
||||||
if (temp) {
|
if (temp) {
|
||||||
|
@ -508,9 +515,12 @@ void DataEndpoint::setCallRecord(DataConsumer* consumer)
|
||||||
return;
|
return;
|
||||||
DataConsumer *temp = m_callRecord;
|
DataConsumer *temp = m_callRecord;
|
||||||
if (consumer) {
|
if (consumer) {
|
||||||
consumer->ref();
|
if (consumer->ref()) {
|
||||||
if (m_source)
|
if (m_source)
|
||||||
DataTranslator::attachChain(m_source,consumer);
|
DataTranslator::attachChain(m_source,consumer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
consumer = 0;
|
||||||
}
|
}
|
||||||
m_callRecord = consumer;
|
m_callRecord = consumer;
|
||||||
if (temp) {
|
if (temp) {
|
||||||
|
|
|
@ -222,7 +222,13 @@ bool MutexPrivate::lock(long maxwait)
|
||||||
if (rval) {
|
if (rval) {
|
||||||
s_locks++;
|
s_locks++;
|
||||||
m_locked++;
|
m_locked++;
|
||||||
m_owner = Thread::currentName();
|
Thread* thr = Thread::current();
|
||||||
|
if (thr) {
|
||||||
|
thr->m_locks++;
|
||||||
|
m_owner = thr->name();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_owner = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
deref();
|
deref();
|
||||||
|
@ -238,6 +244,9 @@ void MutexPrivate::unlock()
|
||||||
// Hope we don't hit a bug related to the debug mutex!
|
// Hope we don't hit a bug related to the debug mutex!
|
||||||
GlobalMutex::lock();
|
GlobalMutex::lock();
|
||||||
if (m_locked) {
|
if (m_locked) {
|
||||||
|
Thread* thr = Thread::current();
|
||||||
|
if (thr)
|
||||||
|
thr->m_locks--;
|
||||||
if (!--m_locked)
|
if (!--m_locked)
|
||||||
m_owner = 0;
|
m_owner = 0;
|
||||||
if (--s_locks < 0)
|
if (--s_locks < 0)
|
||||||
|
|
|
@ -58,7 +58,6 @@ public:
|
||||||
bool m_updest;
|
bool m_updest;
|
||||||
bool m_cancel;
|
bool m_cancel;
|
||||||
const char* m_name;
|
const char* m_name;
|
||||||
private:
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
static void startFunc(void* arg);
|
static void startFunc(void* arg);
|
||||||
#else
|
#else
|
||||||
|
@ -66,7 +65,6 @@ private:
|
||||||
#endif
|
#endif
|
||||||
static void cleanupFunc(void* arg);
|
static void cleanupFunc(void* arg);
|
||||||
static void destroyFunc(void* arg);
|
static void destroyFunc(void* arg);
|
||||||
static void keyAllocFunc();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -81,7 +79,18 @@ using namespace TelEngine;
|
||||||
DWORD tls_index = ::TlsAlloc();
|
DWORD tls_index = ::TlsAlloc();
|
||||||
#else
|
#else
|
||||||
static pthread_key_t current_key;
|
static pthread_key_t current_key;
|
||||||
static pthread_once_t current_key_once = PTHREAD_ONCE_INIT;
|
|
||||||
|
class ThreadPrivateKeyAlloc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ThreadPrivateKeyAlloc()
|
||||||
|
{
|
||||||
|
if (::pthread_key_create(¤t_key,ThreadPrivate::destroyFunc))
|
||||||
|
Debug(DebugFail,"Failed to create current thread key!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ThreadPrivateKeyAlloc keyAllocator;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static TokenDict s_prio[] = {
|
static TokenDict s_prio[] = {
|
||||||
|
@ -247,7 +256,6 @@ void ThreadPrivate::run()
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
::TlsSetValue(tls_index,this);
|
::TlsSetValue(tls_index,this);
|
||||||
#else
|
#else
|
||||||
::pthread_once(¤t_key_once,keyAllocFunc);
|
|
||||||
::pthread_setspecific(current_key,this);
|
::pthread_setspecific(current_key,this);
|
||||||
pthread_cleanup_push(cleanupFunc,this);
|
pthread_cleanup_push(cleanupFunc,this);
|
||||||
::pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,0);
|
::pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,0);
|
||||||
|
@ -273,9 +281,10 @@ bool ThreadPrivate::cancel(bool hard)
|
||||||
ret = false;
|
ret = false;
|
||||||
if (hard) {
|
if (hard) {
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
Debug(DebugFail,"ThreadPrivate terminating win32 thread %lu [%p]",thread,this);
|
Debug(DebugGoOn,"ThreadPrivate terminating win32 thread %lu [%p]",thread,this);
|
||||||
ret = ::TerminateThread(reinterpret_cast<HANDLE>(thread),0) != 0;
|
ret = ::TerminateThread(reinterpret_cast<HANDLE>(thread),0) != 0;
|
||||||
#else
|
#else
|
||||||
|
Debug(DebugMild,"ThreadPrivate terminating pthread %p [%p]",&thread,this);
|
||||||
ret = !::pthread_cancel(thread);
|
ret = !::pthread_cancel(thread);
|
||||||
#endif
|
#endif
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -296,9 +305,11 @@ void ThreadPrivate::cleanup()
|
||||||
if (m_thread->m_private == this) {
|
if (m_thread->m_private == this) {
|
||||||
m_thread->m_private = 0;
|
m_thread->m_private = 0;
|
||||||
m_thread->cleanup();
|
m_thread->cleanup();
|
||||||
|
if (m_thread->locks())
|
||||||
|
Debug(DebugFail,"Thread '%s' destroyed with %d mutex locks [%p]",m_name,m_thread->locks(),m_thread);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Debug(DebugWarn,"ThreadPrivate::cleanup() %p '%s' mismatching %p [%p]",m_thread,m_name,m_thread->m_private,this);
|
Debug(DebugFail,"ThreadPrivate::cleanup() %p '%s' mismatching %p [%p]",m_thread,m_name,m_thread->m_private,this);
|
||||||
m_thread = 0;
|
m_thread = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -390,15 +401,6 @@ void ThreadPrivate::cleanupFunc(void* arg)
|
||||||
t->cleanup();
|
t->cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadPrivate::keyAllocFunc()
|
|
||||||
{
|
|
||||||
#ifndef _WINDOWS
|
|
||||||
DDebug(DebugAll,"ThreadPrivate::keyAllocFunc()");
|
|
||||||
if (::pthread_key_create(¤t_key,destroyFunc))
|
|
||||||
Debug(DebugGoOn,"Failed to create current thread key!");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
void ThreadPrivate::startFunc(void* arg)
|
void ThreadPrivate::startFunc(void* arg)
|
||||||
#else
|
#else
|
||||||
|
@ -422,7 +424,7 @@ Runnable::~Runnable()
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread::Thread(const char* name, Priority prio)
|
Thread::Thread(const char* name, Priority prio)
|
||||||
: m_private(0)
|
: m_private(0), m_locks(0)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
Debugger debug("Thread::Thread","(\"%s\",%d) [%p]",name,prio,this);
|
Debugger debug("Thread::Thread","(\"%s\",%d) [%p]",name,prio,this);
|
||||||
|
@ -431,7 +433,7 @@ Thread::Thread(const char* name, Priority prio)
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread::Thread(const char *name, const char* prio)
|
Thread::Thread(const char *name, const char* prio)
|
||||||
: m_private(0)
|
: m_private(0), m_locks(0)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
Debugger debug("Thread::Thread","(\"%s\",\"%s\") [%p]",name,prio,this);
|
Debugger debug("Thread::Thread","(\"%s\",\"%s\") [%p]",name,prio,this);
|
||||||
|
|
|
@ -2731,6 +2731,7 @@ public:
|
||||||
class YATE_API Thread : public Runnable
|
class YATE_API Thread : public Runnable
|
||||||
{
|
{
|
||||||
friend class ThreadPrivate;
|
friend class ThreadPrivate;
|
||||||
|
friend class MutexPrivate;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Running priorities, their mapping is operating system dependent
|
* Running priorities, their mapping is operating system dependent
|
||||||
|
@ -2766,6 +2767,13 @@ public:
|
||||||
*/
|
*/
|
||||||
bool running() const;
|
bool running() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count how many Yate mutexes are kept locked by this thread
|
||||||
|
* @return Number of Mutex locks held by this thread
|
||||||
|
*/
|
||||||
|
inline int locks() const
|
||||||
|
{ return m_locks; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of this thread
|
* Get the name of this thread
|
||||||
* @return The pointer that was passed in the constructor
|
* @return The pointer that was passed in the constructor
|
||||||
|
@ -2895,6 +2903,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ThreadPrivate* m_private;
|
ThreadPrivate* m_private;
|
||||||
|
int m_locks;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue