diff options
Diffstat (limited to 'indra/llcommon/llthread.cpp')
| -rw-r--r-- | indra/llcommon/llthread.cpp | 241 | 
1 files changed, 137 insertions, 104 deletions
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index bdde1b5c48..4063cc730b 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -36,12 +36,6 @@  #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) @@ -62,6 +56,12 @@ U32 LLThread::sIDIter = 0;  //   //---------------------------------------------------------------------------- +#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,12 +79,9 @@ 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; +	sThreadID = threadp->mID;  #endif -	// Create a thread local data. -	LLThreadLocalData::create(threadp); -  	// Run the user supplied function  	threadp->run(); @@ -97,22 +94,40 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap  } -LLThread::LLThread(std::string const& name) : -	mPaused(false), +LLThread::LLThread(const std::string& name, apr_pool_t *poolp) : +	mPaused(FALSE),  	mName(name),  	mAPRThreadp(NULL), -	mStatus(STOPPED), -	mThreadLocalData(NULL) +	mStatus(STOPPED)  { -	mID = ++sIDIter; //flaw: assume this is called only in the main thread! +	mID = ++sIDIter; -	mRunCondition = new LLCondition; +	// 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 ;  }  LLThread::~LLThread()  {  	shutdown(); + +	if(mLocalAPRFilePoolp) +	{ +		delete mLocalAPRFilePoolp ; +		mLocalAPRFilePoolp = NULL ; +	}  }  void LLThread::shutdown() @@ -149,7 +164,7 @@ void LLThread::shutdown()  		if (!isStopped())  		{  			// This thread just wouldn't stop, even though we gave it time -			//llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl; +			//llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;  			// Put a stake in its heart.  			apr_thread_exit(mAPRThreadp, -1);  			return; @@ -159,8 +174,15 @@ void LLThread::shutdown()  	delete mRunCondition;  	mRunCondition = 0; +	 +	if (mIsLocalPool && mAPRPoolp) +	{ +		apr_pool_destroy(mAPRPoolp); +		mAPRPoolp = 0; +	}  } +  void LLThread::start()  {  	llassert(isStopped()); @@ -169,7 +191,7 @@ void LLThread::start()  	mStatus = RUNNING;  	apr_status_t status = -		apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool()); +		apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);  	if(status == APR_SUCCESS)  	{	 @@ -194,7 +216,7 @@ void LLThread::pause()  	if (!mPaused)  	{  		// this will cause the thread to stop execution as soon as checkPause() is called -		mPaused = true;		// Does not need to be atomic since this is only set/unset from the main thread +		mPaused = 1;		// Does not need to be atomic since this is only set/unset from the main thread  	}	  } @@ -202,7 +224,7 @@ void LLThread::unpause()  {  	if (mPaused)  	{ -		mPaused = false; +		mPaused = 0;  	}  	wake(); // wake up the thread if necessary @@ -279,76 +301,116 @@ void LLThread::wakeLocked()  	}  } -#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; +//============================================================================ -//static -void LLThreadLocalData::init(void) +LLMutex::LLMutex(apr_pool_t *poolp) : +	mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)  { -	// Only do this once. -	if (sThreadLocalDataKey) +	//if (poolp) +	//{ +	//	mIsLocalPool = FALSE; +	//	mAPRPoolp = poolp; +	//} +	//else  	{ -		return; +		mIsLocalPool = TRUE; +		apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread  	} +	apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp); +} -	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. - -	// Create the thread-local data for the main thread (this function is called by the main thread). -	LLThreadLocalData::create(NULL); -#ifdef SHOW_ASSERT -	// This function is called by the main thread. -	main_thread_id = apr_os_thread_current(); +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); +	}  } -// This is called once for every thread when the thread is destructed. -//static -void LLThreadLocalData::destroy(void* thread_local_data) + +void LLMutex::lock()  { -	delete static_cast<LLThreadLocalData*>(thread_local_data); +#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 + +#if LL_DARWIN +	mLockingThread = LLThread::currentID(); +#else +	mLockingThread = sThreadID; +#endif  } -//static -void LLThreadLocalData::create(LLThread* threadp) +void LLMutex::unlock()  { -	LLThreadLocalData* new_tld = new LLThreadLocalData; -	if (threadp) -	{ -		threadp->mThreadLocalData = new_tld; +	if (mCount > 0) +	{ //not the root unlock +		mCount--; +		return;  	} -	apr_status_t status = apr_threadkey_private_set(new_tld, sThreadLocalDataKey); -	llassert_always(status == APR_SUCCESS); +	 +#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);  } -//static -LLThreadLocalData& LLThreadLocalData::tldata(void) +bool LLMutex::isLocked()  { -	if (!sThreadLocalDataKey) +	apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp); +	if (APR_STATUS_IS_EBUSY(status))  	{ -		LLThreadLocalData::init(); +		return true;  	} +	else +	{ +		apr_thread_mutex_unlock(mAPRMutexp); +		return false; +	} +} -	void* data; -	apr_status_t status = apr_threadkey_private_get(&data, sThreadLocalDataKey); -	llassert_always(status == APR_SUCCESS); -	return *static_cast<LLThreadLocalData*>(data); +U32 LLMutex::lockingThread() const +{ +	return mLockingThread;  }  //============================================================================ -LLCondition::LLCondition(LLAPRPool& parent) : LLMutex(parent) +LLCondition::LLCondition(apr_pool_t *poolp) : +	LLMutex(poolp)  { -	apr_thread_cond_create(&mAPRCondp, mPool()); +	// base class (LLMutex) has already ensured that mAPRPoolp is set up. + +	apr_thread_cond_create(&mAPRCondp, mAPRPoolp);  } @@ -361,6 +423,15 @@ 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);  } @@ -375,44 +446,6 @@ 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);  -}  //---------------------------------------------------------------------------- @@ -424,7 +457,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount()  {  	if (!sMutex)  	{ -		sMutex = new LLMutex; +		sMutex = new LLMutex(0);  	}  }  | 
