From 264608d008fcd50ae38762e281cdc12f59d34aa3 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 22 Jan 2009 23:44:03 +0000 Subject: [PATCH] protect threaded pstats better --- panda/src/pipeline/lightMutexDirect.h | 9 ++++++ panda/src/pipeline/lightReMutexDirect.cxx | 4 +++ panda/src/pipeline/lightReMutexDirect.h | 6 +++- panda/src/pipeline/mutexDebug.cxx | 35 +++++++++++++++++++++-- panda/src/pipeline/mutexDebug.h | 5 ++++ panda/src/pstatclient/pStatClientImpl.cxx | 7 +++++ 6 files changed, 63 insertions(+), 3 deletions(-) diff --git a/panda/src/pipeline/lightMutexDirect.h b/panda/src/pipeline/lightMutexDirect.h index 8938f44b64..19b6d46a9e 100644 --- a/panda/src/pipeline/lightMutexDirect.h +++ b/panda/src/pipeline/lightMutexDirect.h @@ -49,7 +49,16 @@ PUBLISHED: void output(ostream &out) const; private: +#ifdef DO_PSTATS + // When PStats is compiled in, we use the full implementation of + // LightMutex, even in the SIMPLE_THREADS case. We have to do this + // since any PStatTimer call may trigger a context switch, and any + // low-level context switch requires all containing mutexes to be + // true mutexes. + MutexTrueImpl _impl; +#else MutexImpl _impl; +#endif // DO_PSTATS }; INLINE ostream & diff --git a/panda/src/pipeline/lightReMutexDirect.cxx b/panda/src/pipeline/lightReMutexDirect.cxx index bd43110698..6f0d682b0d 100644 --- a/panda/src/pipeline/lightReMutexDirect.cxx +++ b/panda/src/pipeline/lightReMutexDirect.cxx @@ -15,6 +15,8 @@ #include "lightReMutexDirect.h" #include "thread.h" +#ifndef DEBUG_THREADS + //////////////////////////////////////////////////////////////////// // Function: LightReMutexDirect::output // Access: Published @@ -25,3 +27,5 @@ void LightReMutexDirect:: output(ostream &out) const { out << "LightReMutex " << (void *)this; } + +#endif // !DEBUG_THREADS diff --git a/panda/src/pipeline/lightReMutexDirect.h b/panda/src/pipeline/lightReMutexDirect.h index 00dafe19bf..186c1bca0f 100644 --- a/panda/src/pipeline/lightReMutexDirect.h +++ b/panda/src/pipeline/lightReMutexDirect.h @@ -21,6 +21,8 @@ class Thread; +#ifndef DEBUG_THREADS + //////////////////////////////////////////////////////////////////// // Class : LightReMutexDirect // Description : This class implements a standard lightReMutex by making @@ -51,7 +53,7 @@ PUBLISHED: void output(ostream &out) const; private: -#ifdef HAVE_REMUTEXIMPL +#if defined(HAVE_REMUTEXIMPL) && !defined(DO_PSTATS) ReMutexImpl _impl; #else @@ -69,4 +71,6 @@ operator << (ostream &out, const LightReMutexDirect &m) { #include "lightReMutexDirect.I" +#endif // !DEBUG_THREADS + #endif diff --git a/panda/src/pipeline/mutexDebug.cxx b/panda/src/pipeline/mutexDebug.cxx index 5bf3082e68..8e376b8147 100755 --- a/panda/src/pipeline/mutexDebug.cxx +++ b/panda/src/pipeline/mutexDebug.cxx @@ -18,6 +18,7 @@ #ifdef DEBUG_THREADS +int MutexDebug::_pstats_count = 0; MutexTrueImpl *MutexDebug::_global_lock; //////////////////////////////////////////////////////////////////// @@ -100,6 +101,36 @@ output_with_holder(ostream &out) const { _global_lock->release(); } +//////////////////////////////////////////////////////////////////// +// Function: MutexDebug::increment_pstats +// Access: Public, Static +// Description: Intended to be called only by +// PStatClientImpl::client_connect(), this tells the +// global mutex system that PStats is active. Once +// PStats is active, all "light" mutexes are treated the +// same as full mutexes. +//////////////////////////////////////////////////////////////////// +void MutexDebug:: +increment_pstats() { + _global_lock->acquire(); + ++_pstats_count; + _global_lock->release(); +} + +//////////////////////////////////////////////////////////////////// +// Function: MutexDebug::decrement_pstats +// Access: Public, Static +// Description: Intended to be called only by +// PStatClientImpl::client_disconnect(), this tells the +// global mutex system that PStats is no longer active. +//////////////////////////////////////////////////////////////////// +void MutexDebug:: +decrement_pstats() { + _global_lock->acquire(); + --_pstats_count; + _global_lock->release(); +} + //////////////////////////////////////////////////////////////////// // Function: MutexDebug::do_acquire // Access: Private @@ -144,7 +175,7 @@ do_acquire(Thread *current_thread) { } else { // The mutex is locked by some other thread. - if (_lightweight) { + if (_lightweight && _pstats_count == 0) { // In this case, it's not a real mutex. Just watch it go by. MissedThreads::iterator mi = _missed_threads.insert(MissedThreads::value_type(current_thread, 0)).first; if ((*mi).second == 0) { @@ -263,7 +294,7 @@ do_try_acquire(Thread *current_thread) { } else { // The mutex is locked by some other thread. Return false. - if (_lightweight) { + if (_lightweight && _pstats_count == 0) { // In this case, it's not a real mutex. Just watch it go by. MissedThreads::iterator mi = _missed_threads.insert(MissedThreads::value_type(current_thread, 0)).first; if ((*mi).second == 0) { diff --git a/panda/src/pipeline/mutexDebug.h b/panda/src/pipeline/mutexDebug.h index 4be732370c..2f5e4ecc93 100644 --- a/panda/src/pipeline/mutexDebug.h +++ b/panda/src/pipeline/mutexDebug.h @@ -49,6 +49,10 @@ PUBLISHED: typedef void VoidFunc(); +public: + static void increment_pstats(); + static void decrement_pstats(); + private: void do_acquire(Thread *current_thread); bool do_try_acquire(Thread *current_thread); @@ -72,6 +76,7 @@ private: ConditionVarImpl _cvar_impl; + static int _pstats_count; static MutexTrueImpl *_global_lock; friend class ConditionVarDebug; diff --git a/panda/src/pstatclient/pStatClientImpl.cxx b/panda/src/pstatclient/pStatClientImpl.cxx index 849a10a53f..9b8ca06c48 100644 --- a/panda/src/pstatclient/pStatClientImpl.cxx +++ b/panda/src/pstatclient/pStatClientImpl.cxx @@ -127,6 +127,10 @@ client_connect(string hostname, int port) { send_hello(); +#ifdef DEBUG_THREADS + MutexDebug::increment_pstats(); +#endif // DEBUG_THREADS + return _is_connected; } @@ -138,6 +142,9 @@ client_connect(string hostname, int port) { void PStatClientImpl:: client_disconnect() { if (_is_connected) { +#ifdef DEBUG_THREADS + MutexDebug::decrement_pstats(); +#endif // DEBUG_THREADS _reader.remove_connection(_tcp_connection); close_connection(_tcp_connection); close_connection(_udp_connection);