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.cpp241
1 files changed, 104 insertions, 137 deletions
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 4063cc730b..bdde1b5c48 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -36,6 +36,12 @@
#include <sched.h>
#endif
+#if !LL_DARWIN
+U32 ll_thread_local local_thread_ID = 0;
+#endif
+
+U32 LLThread::sIDIter = 0;
+
//----------------------------------------------------------------------------
// Usage:
// void run_func(LLThread* thread)
@@ -56,12 +62,6 @@
//
//----------------------------------------------------------------------------
-#if !LL_DARWIN
-U32 ll_thread_local sThreadID = 0;
-#endif
-
-U32 LLThread::sIDIter = 0;
-
LL_COMMON_API void assert_main_thread()
{
static U32 s_thread_id = LLThread::currentID();
@@ -79,9 +79,12 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
LLThread *threadp = (LLThread *)datap;
#if !LL_DARWIN
- sThreadID = threadp->mID;
+ local_thread_ID = threadp->mID;
#endif
+ // Create a thread local data.
+ LLThreadLocalData::create(threadp);
+
// Run the user supplied function
threadp->run();
@@ -94,40 +97,22 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
}
-LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
- mPaused(FALSE),
+LLThread::LLThread(std::string const& name) :
+ mPaused(false),
mName(name),
mAPRThreadp(NULL),
- mStatus(STOPPED)
+ mStatus(STOPPED),
+ mThreadLocalData(NULL)
{
- mID = ++sIDIter;
+ mID = ++sIDIter; //flaw: assume this is called only in the main thread!
- // Thread creation probably CAN be paranoid about APR being initialized, if necessary
- if (poolp)
- {
- mIsLocalPool = FALSE;
- mAPRPoolp = poolp;
- }
- else
- {
- mIsLocalPool = TRUE;
- apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
- }
- mRunCondition = new LLCondition(mAPRPoolp);
-
- mLocalAPRFilePoolp = NULL ;
+ mRunCondition = new LLCondition;
}
LLThread::~LLThread()
{
shutdown();
-
- if(mLocalAPRFilePoolp)
- {
- delete mLocalAPRFilePoolp ;
- mLocalAPRFilePoolp = NULL ;
- }
}
void LLThread::shutdown()
@@ -164,7 +149,7 @@ void LLThread::shutdown()
if (!isStopped())
{
// This thread just wouldn't stop, even though we gave it time
- //llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;
+ //llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl;
// Put a stake in its heart.
apr_thread_exit(mAPRThreadp, -1);
return;
@@ -174,15 +159,8 @@ void LLThread::shutdown()
delete mRunCondition;
mRunCondition = 0;
-
- if (mIsLocalPool && mAPRPoolp)
- {
- apr_pool_destroy(mAPRPoolp);
- mAPRPoolp = 0;
- }
}
-
void LLThread::start()
{
llassert(isStopped());
@@ -191,7 +169,7 @@ void LLThread::start()
mStatus = RUNNING;
apr_status_t status =
- apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
+ apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool());
if(status == APR_SUCCESS)
{
@@ -216,7 +194,7 @@ void LLThread::pause()
if (!mPaused)
{
// this will cause the thread to stop execution as soon as checkPause() is called
- mPaused = 1; // Does not need to be atomic since this is only set/unset from the main thread
+ mPaused = true; // Does not need to be atomic since this is only set/unset from the main thread
}
}
@@ -224,7 +202,7 @@ void LLThread::unpause()
{
if (mPaused)
{
- mPaused = 0;
+ mPaused = false;
}
wake(); // wake up the thread if necessary
@@ -301,116 +279,76 @@ 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);
-}
+#ifdef SHOW_ASSERT
+// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread.
+static apr_os_thread_t main_thread_id;
+LL_COMMON_API bool is_main_thread(void) { return apr_os_thread_equal(main_thread_id, apr_os_thread_current()); }
+#endif
+// The thread private handle to access the LLThreadLocalData instance.
+apr_threadkey_t* LLThreadLocalData::sThreadLocalDataKey;
-LLMutex::~LLMutex()
+//static
+void LLThreadLocalData::init(void)
{
-#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)
+ // Only do this once.
+ if (sThreadLocalDataKey)
{
- apr_pool_destroy(mAPRPoolp);
+ return;
}
-}
+ apr_status_t status = apr_threadkey_private_create(&sThreadLocalDataKey, &LLThreadLocalData::destroy, LLAPRRootPool::get()());
+ ll_apr_assert_status(status); // Or out of memory, or system-imposed limit on the
+ // total number of keys per process {PTHREAD_KEYS_MAX}
+ // has been exceeded.
-void LLMutex::lock()
-{
-#if LL_DARWIN
- if (mLockingThread == LLThread::currentID())
-#else
- if (mLockingThread == sThreadID)
-#endif
- { //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
+ // Create the thread-local data for the main thread (this function is called by the main thread).
+ LLThreadLocalData::create(NULL);
-#if LL_DARWIN
- mLockingThread = LLThread::currentID();
-#else
- mLockingThread = sThreadID;
+#ifdef SHOW_ASSERT
+ // This function is called by the main thread.
+ main_thread_id = apr_os_thread_current();
#endif
}
-void LLMutex::unlock()
+// This is called once for every thread when the thread is destructed.
+//static
+void LLThreadLocalData::destroy(void* thread_local_data)
{
- 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);
+ delete static_cast<LLThreadLocalData*>(thread_local_data);
}
-bool LLMutex::isLocked()
+//static
+void LLThreadLocalData::create(LLThread* threadp)
{
- apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
- if (APR_STATUS_IS_EBUSY(status))
+ LLThreadLocalData* new_tld = new LLThreadLocalData;
+ if (threadp)
{
- return true;
- }
- else
- {
- apr_thread_mutex_unlock(mAPRMutexp);
- return false;
+ threadp->mThreadLocalData = new_tld;
}
+ apr_status_t status = apr_threadkey_private_set(new_tld, sThreadLocalDataKey);
+ llassert_always(status == APR_SUCCESS);
}
-U32 LLMutex::lockingThread() const
+//static
+LLThreadLocalData& LLThreadLocalData::tldata(void)
{
- return mLockingThread;
+ if (!sThreadLocalDataKey)
+ {
+ LLThreadLocalData::init();
+ }
+
+ void* data;
+ apr_status_t status = apr_threadkey_private_get(&data, sThreadLocalDataKey);
+ llassert_always(status == APR_SUCCESS);
+ return *static_cast<LLThreadLocalData*>(data);
}
//============================================================================
-LLCondition::LLCondition(apr_pool_t *poolp) :
- LLMutex(poolp)
+LLCondition::LLCondition(LLAPRPool& parent) : LLMutex(parent)
{
- // base class (LLMutex) has already ensured that mAPRPoolp is set up.
-
- apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
+ apr_thread_cond_create(&mAPRCondp, mPool());
}
@@ -423,15 +361,6 @@ LLCondition::~LLCondition()
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);
}
@@ -446,6 +375,44 @@ void LLCondition::broadcast()
}
//============================================================================
+LLMutexBase::LLMutexBase() :
+ mLockingThread(NO_THREAD),
+ mCount(0)
+{
+}
+
+void LLMutexBase::lock()
+{
+#if LL_DARWIN
+ if (mLockingThread == LLThread::currentID())
+#else
+ if (mLockingThread == local_thread_ID)
+#endif
+ { //redundant lock
+ mCount++;
+ return;
+ }
+
+ apr_thread_mutex_lock(mAPRMutexp);
+
+#if LL_DARWIN
+ mLockingThread = LLThread::currentID();
+#else
+ mLockingThread = local_thread_ID;
+#endif
+}
+
+void LLMutexBase::unlock()
+{
+ if (mCount > 0)
+ { //not the root unlock
+ mCount--;
+ return;
+ }
+ mLockingThread = NO_THREAD;
+
+ apr_thread_mutex_unlock(mAPRMutexp);
+}
//----------------------------------------------------------------------------
@@ -457,7 +424,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount()
{
if (!sMutex)
{
- sMutex = new LLMutex(0);
+ sMutex = new LLMutex;
}
}