Add AIThreadID - Cleanup of apr_os_thread* related code.
Apart from just really cleaning things up and moving everything into one class regarding thread IDs (ie, is_main_thread(), comparing ID's etc), this also fixes an obscure bug where LL was casting thread ID's to U32 and then compared those to find out if it the same thread. It's theoretically possible that such fails on a 64bit OS. By generalizing the interface, I adopted the use of a thread-local cache for the current thread ID as used by LLMutex et al, so now all code benefits from that. The idea was even extended to now also be used for is_main_thread() tests and even resetting a thread ID to the ID of the current thread.
This commit is contained in:
@@ -67,18 +67,12 @@
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if !LL_DARWIN
|
||||
U32 ll_thread_local local_thread_ID = 0;
|
||||
#endif
|
||||
|
||||
U32 LLThread::sIDIter = 0;
|
||||
LLAtomicS32 LLThread::sCount = 0;
|
||||
LLAtomicS32 LLThread::sRunning = 0;
|
||||
|
||||
LL_COMMON_API void assert_main_thread()
|
||||
{
|
||||
static U32 s_thread_id = LLThread::currentID();
|
||||
if (LLThread::currentID() != s_thread_id)
|
||||
if (!AIThreadID::in_main_thread())
|
||||
{
|
||||
llerrs << "Illegal execution outside main thread." << llendl;
|
||||
}
|
||||
@@ -95,9 +89,8 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
|
||||
|
||||
LLThread *threadp = (LLThread *)datap;
|
||||
|
||||
#if !LL_DARWIN
|
||||
local_thread_ID = threadp->mID;
|
||||
#endif
|
||||
// Initialize thread-local cache of current thread ID (if supported).
|
||||
AIThreadID::set_current_thread_id();
|
||||
|
||||
// Create a thread local data.
|
||||
LLThreadLocalData::create(threadp);
|
||||
@@ -137,7 +130,6 @@ LLThread::LLThread(std::string const& name) :
|
||||
mStatus(STOPPED),
|
||||
mThreadLocalData(NULL)
|
||||
{
|
||||
mID = ++sIDIter;
|
||||
sCount++;
|
||||
llassert(sCount <= 50);
|
||||
mRunCondition = new LLCondition;
|
||||
@@ -281,12 +273,6 @@ void LLThread::setQuitting()
|
||||
wake();
|
||||
}
|
||||
|
||||
// static
|
||||
U32 LLThread::currentID()
|
||||
{
|
||||
return (U32)apr_os_thread_current();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLThread::yield()
|
||||
{
|
||||
@@ -315,14 +301,6 @@ void LLThread::wakeLocked()
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
apr_os_thread_t LLThread::sMainThreadID;
|
||||
|
||||
void LLThread::set_main_thread_id(void)
|
||||
{
|
||||
sMainThreadID = apr_os_thread_current();
|
||||
}
|
||||
|
||||
// The thread private handle to access the LLThreadLocalData instance.
|
||||
apr_threadkey_t* LLThreadLocalData::sThreadLocalDataKey;
|
||||
|
||||
@@ -345,6 +323,10 @@ void LLThreadLocalData::init(void)
|
||||
return;
|
||||
}
|
||||
|
||||
// This function is called by the main thread (these values are also needed in the next line).
|
||||
AIThreadID::set_main_thread_id();
|
||||
AIThreadID::set_current_thread_id();
|
||||
|
||||
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}
|
||||
@@ -352,9 +334,6 @@ void LLThreadLocalData::init(void)
|
||||
|
||||
// Create the thread-local data for the main thread (this function is called by the main thread).
|
||||
LLThreadLocalData::create(NULL);
|
||||
|
||||
// This function is called by the main thread.
|
||||
LLThread::set_main_thread_id();
|
||||
}
|
||||
|
||||
// This is called once for every thread when the thread is destructed.
|
||||
@@ -421,27 +400,19 @@ void LLCondition::broadcast()
|
||||
|
||||
//============================================================================
|
||||
LLMutexBase::LLMutexBase() :
|
||||
mLockingThread(NO_THREAD),
|
||||
mLockingThread(AIThreadID::sNone),
|
||||
mCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool LLMutexBase::isSelfLocked() const
|
||||
{
|
||||
#if LL_DARWIN
|
||||
return mLockingThread == LLThread::currentID();
|
||||
#else
|
||||
return mLockingThread == local_thread_ID;
|
||||
#endif
|
||||
return mLockingThread.equals_current_thread();
|
||||
}
|
||||
|
||||
void LLMutexBase::lock()
|
||||
{
|
||||
#if LL_DARWIN
|
||||
if (mLockingThread == LLThread::currentID())
|
||||
#else
|
||||
if (mLockingThread == local_thread_ID)
|
||||
#endif
|
||||
if (mLockingThread.equals_current_thread())
|
||||
{ //redundant lock
|
||||
mCount++;
|
||||
return;
|
||||
@@ -449,11 +420,33 @@ void LLMutexBase::lock()
|
||||
|
||||
apr_thread_mutex_lock(mAPRMutexp);
|
||||
|
||||
#if LL_DARWIN
|
||||
mLockingThread = LLThread::currentID();
|
||||
#else
|
||||
mLockingThread = local_thread_ID;
|
||||
#endif
|
||||
mLockingThread.reset();
|
||||
}
|
||||
|
||||
bool LLMutexBase::tryLock()
|
||||
{
|
||||
if (mLockingThread.equals_current_thread())
|
||||
{ //redundant lock
|
||||
mCount++;
|
||||
return true;
|
||||
}
|
||||
bool success = !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp));
|
||||
if (success)
|
||||
{
|
||||
mLockingThread.reset();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
// non-blocking, but does do a lock/unlock so not free
|
||||
bool LLMutexBase::isLocked() const
|
||||
{
|
||||
if (mLockingThread.equals_current_thread())
|
||||
return false; // A call to lock() won't block.
|
||||
if (APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)))
|
||||
return true;
|
||||
apr_thread_mutex_unlock(mAPRMutexp);
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLMutexBase::unlock()
|
||||
@@ -463,7 +456,7 @@ void LLMutexBase::unlock()
|
||||
mCount--;
|
||||
return;
|
||||
}
|
||||
mLockingThread = NO_THREAD;
|
||||
mLockingThread = AIThreadID::sNone;
|
||||
|
||||
apr_thread_mutex_unlock(mAPRMutexp);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user