Added names to the Mutex class to ease debugging of deadlocks.

git-svn-id: http://yate.null.ro/svn/yate/trunk@2611 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2009-05-05 12:25:31 +00:00
parent edfe266f4d
commit 85da36395b
11 changed files with 44 additions and 47 deletions

View File

@ -62,11 +62,11 @@ bool TelEngine::isE164(const char* str)
}
static unsigned int s_callid = 0;
static Mutex s_callidMutex;
static Mutex s_callidMutex(false,"CallID");
// this is to protect against two threads trying to (dis)connect a pair
// of call endpoints at the same time
static Mutex s_mutex(true);
static Mutex s_mutex(true,"CallEndpoint");
CallEndpoint::CallEndpoint(const char* id)
: m_peer(0), m_id(id), m_mutex(0)
@ -851,7 +851,7 @@ const char* Module::messageName(int id)
}
Module::Module(const char* name, const char* type, bool earlyInit)
: Plugin(name,earlyInit), Mutex(true),
: Plugin(name,earlyInit), Mutex(true,"Module"),
m_init(false), m_relays(0), m_name(name), m_type(type), m_changed(0)
{
debugName(m_name);

View File

@ -148,9 +148,9 @@ static String s_rejectReason = "Rejected";
static String s_hangupReason = "User hangup";
static String s_cancelReason = "Cancelled";
static unsigned int s_eventLen = 0; // Log maximum lines (0: unlimited)
static Mutex s_debugMutex;
static Mutex s_proxyMutex;
static Mutex s_postponeMutex;
static Mutex s_debugMutex(false,"ClientDebug");
static Mutex s_proxyMutex(false,"ClientProxy");
static Mutex s_postponeMutex(false,"ClientPostpone");
static ObjList s_postponed;
static NamedList* s_debugLog = 0;
static ClientThreadProxy* s_proxy = 0;
@ -186,7 +186,7 @@ String ClientDriver::s_confName = "conf/client"; // The name of the client's con
bool ClientDriver::s_dropConfPeer = true; // Drop a channel's old peer when terminated while in conference
String ClientDriver::s_device; // Currently used audio device
ObjList ClientSound::s_sounds; // ClientSound's list
Mutex ClientSound::s_soundsMutex(true); // ClientSound's list lock mutex
Mutex ClientSound::s_soundsMutex(true,"ClientSound"); // ClientSound's list lock mutex
String ClientSound::s_calltoPrefix = "wave/play/"; // Client sound target prefix
// Client relays
@ -3243,7 +3243,7 @@ ClientChannel* ClientDriver::findChanByPeer(const String& peer)
// Constructor
ClientAccount::ClientAccount(const char* proto, const char* user,
const char* host, bool startup)
: Mutex(true),
: Mutex(true,"ClientAccount"),
m_port(0), m_startup(startup), m_expires(-1), m_connected(false),
m_resource(0)
{
@ -3254,7 +3254,7 @@ ClientAccount::ClientAccount(const char* proto, const char* user,
// Constructor. Build an account from a list of parameters.
ClientAccount::ClientAccount(const NamedList& params)
: Mutex(true),
: Mutex(true,"ClientAccount"),
m_port(0), m_startup(false), m_expires(-1), m_connected(false),
m_resource(0)
{

View File

@ -51,7 +51,7 @@ static unsigned int s_maxCallHistory = 20;
ObjList ClientLogic::s_accOptions;
ObjList ClientLogic::s_protocols;
Mutex ClientLogic::s_protocolsMutex(true);
Mutex ClientLogic::s_protocolsMutex(true,"ClientProtocols");
// Parameters that are applied from provider template
const char* ClientLogic::s_provParams[] = {
"server",
@ -177,7 +177,7 @@ inline void activatePageCalls(ClientLogic* logic, Window* wnd = 0)
*/
// Constructor
ClientLogic::ClientLogic(const char* name, int priority)
: m_durationMutex(true), m_name(name), m_prio(priority)
: m_durationMutex(true,"ClientLogic::duration"), m_name(name), m_prio(priority)
{
Debug(ClientDriver::self(),DebugAll,"ClientLogic(%s) [%p]",m_name.c_str(),this);
Client::addLogic(this);

View File

@ -109,7 +109,7 @@ static TranslatorCaps s_stereoCaps[] = {
{ 0, 0, 0 }
};
static Mutex s_dataMutex(true);
static Mutex s_dataMutex(true,"DataEndpoint");
class ThreadedSourcePrivate : public Thread
{
@ -1079,7 +1079,7 @@ bool DataTranslator::synchronize(DataSource* source)
return true;
}
Mutex DataTranslator::s_mutex(true);
Mutex DataTranslator::s_mutex(true,"DataTranslator");
ObjList DataTranslator::s_factories;
unsigned int DataTranslator::s_maxChain = 3;
static ObjList s_compose;

View File

@ -270,7 +270,8 @@ bool MessageRelay::receivedInternal(Message& msg)
MessageDispatcher::MessageDispatcher()
: m_changes(0), m_warnTime(0)
: Mutex(false,"MessageDispatcher"),
m_changes(0), m_warnTime(0)
{
XDebug(DebugInfo,"MessageDispatcher::MessageDispatcher() [%p]",this);
}

View File

@ -49,7 +49,7 @@ namespace TelEngine {
class MutexPrivate {
public:
MutexPrivate(bool recursive);
MutexPrivate(bool recursive, const char* name);
~MutexPrivate();
inline void ref()
{ ++m_refcount; }
@ -57,6 +57,8 @@ public:
{ if (!--m_refcount) delete this; }
inline bool recursive() const
{ return m_recursive; }
inline const char* name() const
{ return m_name; }
bool locked() const
{ return (m_locked > 0); }
bool lock(long maxwait);
@ -68,6 +70,7 @@ private:
int m_refcount;
volatile unsigned int m_locked;
bool m_recursive;
const char* m_name;
const char* m_owner;
};
@ -140,8 +143,9 @@ void GlobalMutex::unlock()
}
MutexPrivate::MutexPrivate(bool recursive)
: m_refcount(1), m_locked(0), m_recursive(recursive), m_owner(0)
MutexPrivate::MutexPrivate(bool recursive, const char* name)
: m_refcount(1), m_locked(0), m_recursive(recursive),
m_name(name), m_owner(0)
{
GlobalMutex::lock();
s_count++;
@ -185,11 +189,11 @@ MutexPrivate::~MutexPrivate()
#endif
GlobalMutex::unlock();
if (m_locked)
Debug(DebugFail,"MutexPrivate owned by '%s' destroyed with %u locks [%p]",
m_owner,m_locked,this);
Debug(DebugFail,"MutexPrivate '%s' owned by '%s' destroyed with %u locks [%p]",
m_name,m_owner,m_locked,this);
else if (warn)
Debug(DebugGoOn,"MutexPrivate owned by '%s' unlocked in destructor [%p]",
m_owner,this);
Debug(DebugGoOn,"MutexPrivate '%s' owned by '%s' unlocked in destructor [%p]",
m_name,m_owner,this);
}
bool MutexPrivate::lock(long maxwait)
@ -253,8 +257,8 @@ bool MutexPrivate::lock(long maxwait)
deref();
GlobalMutex::unlock();
if (warn && !rval)
Debug(DebugFail,"Thread '%s' could not take lock owned by '%s' for %lu usec!",
Thread::currentName(),m_owner,maxwait);
Debug(DebugFail,"Thread '%s' could not lock mutex '%s' owned by '%s' for %lu usec!",
Thread::currentName(),m_name,m_owner,maxwait);
return rval;
}
@ -269,8 +273,8 @@ void MutexPrivate::unlock()
if (!--m_locked) {
const char* tname = thr ? thr->name() : 0;
if (tname != m_owner)
Debug(DebugFail,"MutexPrivate unlocked by '%s' but owned by '%s' [%p]",
tname,m_owner,this);
Debug(DebugFail,"MutexPrivate '%s' unlocked by '%s' but owned by '%s' [%p]",
m_name,tname,m_owner,this);
m_owner = 0;
}
int locks = --s_locks;
@ -288,21 +292,17 @@ void MutexPrivate::unlock()
deref();
}
else
Debug(DebugFail,"MutexPrivate::unlock called on unlocked mutex [%p]",this);
Debug(DebugFail,"MutexPrivate::unlock called on unlocked '%s' [%p]",m_name,this);
GlobalMutex::unlock();
}
Mutex::Mutex()
Mutex::Mutex(bool recursive, const char* name)
: m_private(0)
{
m_private = new MutexPrivate(false);
}
Mutex::Mutex(bool recursive)
: m_private(0)
{
m_private = new MutexPrivate(recursive);
if (!name)
name = "?";
m_private = new MutexPrivate(recursive,name);
}
Mutex::Mutex(const Mutex &original)

View File

@ -74,7 +74,7 @@
using namespace TelEngine;
static Mutex s_mutex;
static Mutex s_mutex(false,"Socket");
#ifdef _WINDOWS

View File

@ -47,7 +47,7 @@ void srandom(unsigned int seed)
int _gmtime_s(struct tm* _tm, const time_t* time)
{
static TelEngine::Mutex m;
static TelEngine::Mutex m(false,"_gmtime_s");
struct tm* tmp;
if (!_tm)
return EINVAL;
@ -142,8 +142,8 @@ static void dbg_colorize_func(const char* buf, int level)
static void (*s_output)(const char*,int) = dbg_stderr_func;
static void (*s_intout)(const char*,int) = 0;
static Mutex out_mux;
static Mutex ind_mux;
static Mutex out_mux(false,"DebugOutput");
static Mutex ind_mux(false,"DebugIndent");
static Thread* s_thr = 0;
static bool reentered()
@ -610,7 +610,7 @@ void GenObject::destruct()
}
static Mutex s_refmutex;
static Mutex s_refmutex(false,"RefObject");
RefObject::~RefObject()
{

View File

@ -117,7 +117,7 @@ static TokenDict s_prio[] = {
};
static ObjList s_threads;
static Mutex s_tmutex(true);
static Mutex s_tmutex(true,"Thread");
ThreadPrivate* ThreadPrivate::create(Thread* t,const char* name,Thread::Priority prio)
{

View File

@ -2840,7 +2840,7 @@ public:
* @param name List's name used for debug purposes
*/
inline ClientAccountList(const char* name)
: String(name), Mutex(true)
: String(name), Mutex(true,"ClientAccountList")
{}
/**

View File

@ -3544,17 +3544,13 @@ class YATE_API Mutex
{
friend class MutexPrivate;
public:
/**
* Construct a new unlocked fast mutex
*/
Mutex();
/**
* Construct a new unlocked mutex
* @param recursive True if the mutex has to be recursive (reentrant),
* false for a normal fast mutex
* @param name Static name of the mutex (for debugging purpose only)
*/
Mutex(bool recursive);
Mutex(bool recursive = false, const char* name = 0);
/**
* Copy constructor creates a shared mutex