From 0883e02e2964e1444391ae68a85c2283fbc6a1af Mon Sep 17 00:00:00 2001 From: paulc Date: Tue, 9 Nov 2010 19:52:51 +0000 Subject: [PATCH] Added API and -Dd command line parameter to disable taking the global mutex when (un)locking a Mutex or Semaphore. This provides better performance and reduces mutex contention on expense of some thread safety and ease of debugging. git-svn-id: http://yate.null.ro/svn/yate/trunk@3801 acf43c95-373e-0410-b603-e72c3f656dc1 --- docs/man/yate.8 | 3 ++ engine/Engine.cpp | 4 +++ engine/Mutex.cpp | 88 ++++++++++++++++++++++++++++++----------------- yateclass.h | 7 ++++ 4 files changed, 71 insertions(+), 31 deletions(-) diff --git a/docs/man/yate.8 b/docs/man/yate.8 index ea5d0503..fda983d7 100644 --- a/docs/man/yate.8 +++ b/docs/man/yate.8 @@ -99,6 +99,9 @@ Abort (coredumps if allowed) if bugs are encountered .B \-Dm Attempt to debug mutex deadlocks by setting a maximum 10s limit, if repeated halves the limit .TP +.B \-Dd +Disable some locking debugging and safety features, improves performance instead +.TP .B \-Dl Attempt to load modules without having their symbols globally visible .TP diff --git a/engine/Engine.cpp b/engine/Engine.cpp index ad098495..8a71dbc7 100644 --- a/engine/Engine.cpp +++ b/engine/Engine.cpp @@ -1490,6 +1490,7 @@ static void usage(bool client, FILE* f) " -D[options] Special debugging options\n" " a Abort if bugs are encountered\n" " m Attempt to debug mutex deadlocks\n" +" d Disable locking debugging and safety features\n" #ifdef RTLD_GLOBAL " l Try to keep module symbols local\n" #endif @@ -1745,6 +1746,9 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo Lockable::wait(lockWait); } break; + case 'd': + Lockable::disableSafety(); + break; #ifdef RTLD_GLOBAL case 'l': s_localsymbol = true; diff --git a/engine/Mutex.cpp b/engine/Mutex.cpp index 40e9d84f..591b9173 100644 --- a/engine/Mutex.cpp +++ b/engine/Mutex.cpp @@ -131,6 +131,7 @@ HMUTEX GlobalMutex::s_mutex; static GlobalMutex s_global; static unsigned long s_maxwait = 0; static bool s_unsafe = MUTEX_STATIC_UNSAFE; +static bool s_safety = true; volatile int MutexPrivate::s_count = 0; volatile int MutexPrivate::s_locks = 0; @@ -217,7 +218,8 @@ MutexPrivate::~MutexPrivate() if (m_locked) { warn = true; m_locked--; - s_locks--; + if (s_safety) + s_locks--; #ifdef _WINDOWS ::ReleaseMutex(m_mutex); #else @@ -248,13 +250,16 @@ bool MutexPrivate::lock(long maxwait) maxwait = (long)s_maxwait; warn = true; } - GlobalMutex::lock(); + if (s_safety) + GlobalMutex::lock(); ref(); - m_waiting++; Thread* thr = Thread::current(); if (thr) thr->m_locking = true; - GlobalMutex::unlock(); + if (s_safety) { + m_waiting++; + GlobalMutex::unlock(); + } #ifdef _WINDOWS DWORD ms = 0; if (maxwait < 0) @@ -295,12 +300,15 @@ bool MutexPrivate::lock(long maxwait) #endif // HAVE_TIMEDLOCK } #endif // _WINDOWS - GlobalMutex::lock(); + if (s_safety) { + GlobalMutex::lock(); + m_waiting--; + } if (thr) thr->m_locking = false; - m_waiting--; if (rval) { - s_locks++; + if (s_safety) + s_locks++; m_locked++; if (thr) { thr->m_locks++; @@ -311,7 +319,8 @@ bool MutexPrivate::lock(long maxwait) } else deref(); - GlobalMutex::unlock(); + if (s_safety) + GlobalMutex::unlock(); if (warn && !rval) Debug(DebugFail,"Thread '%s' could not lock mutex '%s' owned by '%s' waited by %u others for %lu usec!", Thread::currentName(),m_name,m_owner,m_waiting,maxwait); @@ -322,7 +331,8 @@ bool MutexPrivate::unlock() { bool ok = false; // Hope we don't hit a bug related to the debug mutex! - GlobalMutex::lock(); + if (s_safety) + GlobalMutex::lock(); if (m_locked) { Thread* thr = Thread::current(); if (thr) @@ -334,12 +344,14 @@ bool MutexPrivate::unlock() m_name,tname,m_owner,this); m_owner = 0; } - int locks = --s_locks; - if (locks < 0) { - // this is very very bad - abort right now - abortOnBug(true); - s_locks = 0; - Debug(DebugFail,"MutexPrivate::locks() is %d [%p]",locks,this); + if (s_safety) { + int locks = --s_locks; + if (locks < 0) { + // this is very very bad - abort right now + abortOnBug(true); + s_locks = 0; + Debug(DebugFail,"MutexPrivate::locks() is %d [%p]",locks,this); + } } if (!s_unsafe) #ifdef _WINDOWS @@ -352,7 +364,8 @@ bool MutexPrivate::unlock() } else Debug(DebugFail,"MutexPrivate::unlock called on unlocked '%s' [%p]",m_name,this); - GlobalMutex::unlock(); + if (s_safety) + GlobalMutex::unlock(); return ok; } @@ -395,14 +408,17 @@ bool SemaphorePrivate::lock(long maxwait) maxwait = (long)s_maxwait; warn = true; } - GlobalMutex::lock(); + if (s_safety) + GlobalMutex::lock(); ref(); - s_locks++; - m_waiting++; Thread* thr = Thread::current(); if (thr) thr->m_locking = true; - GlobalMutex::unlock(); + if (s_safety) { + s_locks++; + m_waiting++; + GlobalMutex::unlock(); + } #ifdef _WINDOWS DWORD ms = 0; if (maxwait < 0) @@ -443,19 +459,22 @@ bool SemaphorePrivate::lock(long maxwait) #endif // HAVE_TIMEDWAIT } #endif // _WINDOWS - GlobalMutex::lock(); - m_waiting--; - int locks = --s_locks; - if (locks < 0) { - // this is very very bad - abort right now - abortOnBug(true); - s_locks = 0; - Debug(DebugFail,"SemaphorePrivate::locks() is %d [%p]",locks,this); + if (s_safety) { + GlobalMutex::lock(); + int locks = --s_locks; + if (locks < 0) { + // this is very very bad - abort right now + abortOnBug(true); + s_locks = 0; + Debug(DebugFail,"SemaphorePrivate::locks() is %d [%p]",locks,this); + } + m_waiting--; } if (thr) thr->m_locking = false; deref(); - GlobalMutex::unlock(); + if (s_safety) + GlobalMutex::unlock(); if (warn && !rval) Debug(DebugFail,"Thread '%s' could not lock semaphore '%s' waited by %u others for %lu usec!", Thread::currentName(),m_name,m_waiting,maxwait); @@ -464,7 +483,8 @@ bool SemaphorePrivate::lock(long maxwait) bool SemaphorePrivate::unlock() { - GlobalMutex::lock(); + if (s_safety) + GlobalMutex::lock(); ref(); if (!s_unsafe) { #ifdef _WINDOWS @@ -476,7 +496,8 @@ bool SemaphorePrivate::unlock() #endif } deref(); - GlobalMutex::unlock(); + if (s_safety) + GlobalMutex::unlock(); return true; } @@ -508,6 +529,11 @@ void Lockable::startUsingNow() s_unsafe = false; } +void Lockable::disableSafety() +{ + s_safety = false; +} + void Lockable::wait(unsigned long maxwait) { s_maxwait = maxwait; diff --git a/yateclass.h b/yateclass.h index 3baf3bb5..35868dce 100644 --- a/yateclass.h +++ b/yateclass.h @@ -4259,6 +4259,13 @@ public: * before creating any threads and without holding any object locked. */ static void startUsingNow(); + + /** + * Disable some safety and sanity check features. + * This provides a performance improvement but makes the code less safe and + * more difficult to debug locking issues. + */ + static void disableSafety(); }; /**