summaryrefslogtreecommitdiff
path: root/indra/llcommon/llthread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llthread.cpp')
-rw-r--r--indra/llcommon/llthread.cpp238
1 files changed, 229 insertions, 9 deletions
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index cc661bab59..1c86eb4f06 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -65,7 +65,7 @@
U32 __declspec(thread) LLThread::sThreadIndex = 0;
#elif LL_LINUX
U32 __thread LLThread::sThreadID = 0;
-#endif
+#endif
U32 LLThread::sIDIter = 0;
@@ -79,6 +79,13 @@ LL_COMMON_API void assert_main_thread()
}
}
+void LLThread::registerThreadID()
+{
+#if !LL_DARWIN
+ sThreadID = ++sIDIter;
+#endif
+}
+
//
// Handed to the APR thread creation function
//
@@ -126,7 +133,7 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
}
mRunCondition = new LLCondition(mAPRPoolp);
-
+ mDataLock = new LLMutex(mAPRPoolp);
mLocalAPRFilePoolp = NULL ;
}
@@ -185,7 +192,10 @@ void LLThread::shutdown()
}
delete mRunCondition;
- mRunCondition = 0;
+ mRunCondition = NULL;
+
+ delete mDataLock;
+ mDataLock = NULL;
if (mIsLocalPool && mAPRPoolp)
{
@@ -254,28 +264,30 @@ bool LLThread::runCondition(void)
// Stop thread execution if requested until unpaused.
void LLThread::checkPause()
{
- mRunCondition->lock();
+ mDataLock->lock();
// This is in a while loop because the pthread API allows for spurious wakeups.
while(shouldSleep())
{
+ mDataLock->unlock();
mRunCondition->wait(); // unlocks mRunCondition
+ mDataLock->lock();
// mRunCondition is locked when the thread wakes up
}
- mRunCondition->unlock();
+ mDataLock->unlock();
}
//============================================================================
void LLThread::setQuitting()
{
- mRunCondition->lock();
+ mDataLock->lock();
if (mStatus == RUNNING)
{
mStatus = QUITTING;
}
- mRunCondition->unlock();
+ mDataLock->unlock();
wake();
}
@@ -297,12 +309,12 @@ void LLThread::yield()
void LLThread::wake()
{
- mRunCondition->lock();
+ mDataLock->lock();
if(!shouldSleep())
{
mRunCondition->signal();
}
- mRunCondition->unlock();
+ mDataLock->unlock();
}
void LLThread::wakeLocked()
@@ -313,3 +325,211 @@ void LLThread::wakeLocked()
}
}
+//============================================================================
+
+LLMutex::LLMutex(apr_pool_t *poolp) :
+ mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
+{
+ //if (poolp)
+ //{
+ // mIsLocalPool = FALSE;
+ // mAPRPoolp = poolp;
+ //}
+ //else
+ {
+ mIsLocalPool = TRUE;
+ apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
+ }
+ apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
+}
+
+
+LLMutex::~LLMutex()
+{
+#if MUTEX_DEBUG
+ //bad assertion, the subclass LLSignal might be "locked", and that's OK
+ //llassert_always(!isLocked()); // better not be locked!
+#endif
+ apr_thread_mutex_destroy(mAPRMutexp);
+ mAPRMutexp = NULL;
+ if (mIsLocalPool)
+ {
+ apr_pool_destroy(mAPRPoolp);
+ }
+}
+
+
+void LLMutex::lock()
+{
+ if(isSelfLocked())
+ { //redundant lock
+ mCount++;
+ return;
+ }
+
+ apr_thread_mutex_lock(mAPRMutexp);
+
+#if MUTEX_DEBUG
+ // Have to have the lock before we can access the debug info
+ U32 id = LLThread::currentID();
+ if (mIsLocked[id] != FALSE)
+ llerrs << "Already locked in Thread: " << id << llendl;
+ mIsLocked[id] = TRUE;
+#endif
+
+#if LL_DARWIN
+ mLockingThread = LLThread::currentID();
+#else
+ mLockingThread = sThreadID;
+#endif
+}
+
+void LLMutex::unlock()
+{
+ if (mCount > 0)
+ { //not the root unlock
+ mCount--;
+ return;
+ }
+
+#if MUTEX_DEBUG
+ // Access the debug info while we have the lock
+ U32 id = LLThread::currentID();
+ if (mIsLocked[id] != TRUE)
+ llerrs << "Not locked in Thread: " << id << llendl;
+ mIsLocked[id] = FALSE;
+#endif
+
+ mLockingThread = NO_THREAD;
+ apr_thread_mutex_unlock(mAPRMutexp);
+}
+
+bool LLMutex::isLocked()
+{
+ apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
+ if (APR_STATUS_IS_EBUSY(status))
+ {
+ return true;
+ }
+ else
+ {
+ apr_thread_mutex_unlock(mAPRMutexp);
+ return false;
+ }
+}
+
+bool LLMutex::isSelfLocked()
+{
+#if LL_DARWIN
+ return mLockingThread == LLThread::currentID();
+#else
+ return mLockingThread == sThreadID;
+#endif
+}
+
+U32 LLMutex::lockingThread() const
+{
+ return mLockingThread;
+}
+
+//============================================================================
+
+LLCondition::LLCondition(apr_pool_t *poolp) :
+ LLMutex(poolp)
+{
+ // base class (LLMutex) has already ensured that mAPRPoolp is set up.
+
+ apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
+}
+
+
+LLCondition::~LLCondition()
+{
+ apr_thread_cond_destroy(mAPRCondp);
+ mAPRCondp = NULL;
+}
+
+
+void LLCondition::wait()
+{
+ if (!isLocked())
+ { //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
+ apr_thread_mutex_lock(mAPRMutexp);
+#if MUTEX_DEBUG
+ // avoid asserts on destruction in non-release builds
+ U32 id = LLThread::currentID();
+ mIsLocked[id] = TRUE;
+#endif
+ }
+ apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
+}
+
+void LLCondition::signal()
+{
+ apr_thread_cond_signal(mAPRCondp);
+}
+
+void LLCondition::broadcast()
+{
+ apr_thread_cond_broadcast(mAPRCondp);
+}
+
+//============================================================================
+
+//----------------------------------------------------------------------------
+
+//static
+LLMutex* LLThreadSafeRefCount::sMutex = 0;
+
+//static
+void LLThreadSafeRefCount::initThreadSafeRefCount()
+{
+ if (!sMutex)
+ {
+ sMutex = new LLMutex(0);
+ }
+}
+
+//static
+void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
+{
+ delete sMutex;
+ sMutex = NULL;
+}
+
+
+//----------------------------------------------------------------------------
+
+LLThreadSafeRefCount::LLThreadSafeRefCount() :
+ mRef(0)
+{
+}
+
+LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src)
+{
+ if (sMutex)
+ {
+ sMutex->lock();
+ }
+ mRef = 0;
+ if (sMutex)
+ {
+ sMutex->unlock();
+ }
+}
+
+LLThreadSafeRefCount::~LLThreadSafeRefCount()
+{
+ if (mRef != 0)
+ {
+ llerrs << "deleting non-zero reference" << llendl;
+ }
+}
+
+//============================================================================
+
+LLResponder::~LLResponder()
+{
+}
+
+//============================================================================