aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorArmin Weatherwax2010-03-02 14:55:47 +0100
committerArmin Weatherwax2010-03-04 22:38:49 +0100
commit5cad29e95879a5a08cb1a8dabfff8eda17e55763 (patch)
tree3122db3e78f243ce7a5053a7d6c7ea5446537059
parentRobin Cornelius, Aleric Inglewood: SNOW-196 missing mutexes for texture fetch (diff)
downloadmeta-impy-5cad29e95879a5a08cb1a8dabfff8eda17e55763.zip
meta-impy-5cad29e95879a5a08cb1a8dabfff8eda17e55763.tar.gz
meta-impy-5cad29e95879a5a08cb1a8dabfff8eda17e55763.tar.bz2
meta-impy-5cad29e95879a5a08cb1a8dabfff8eda17e55763.tar.xz
Aleric Inglewood: SNOW-196 Special case for TextureFetch race condition check.
Where the current UUID was just removed from mRequestMap, thus avoiding to the need for the problematic lock completely. The case that we add something to mNetworkQueue while it was just removed from mRequestMap is corrected by LLTextureFetch::sendRequestListToSimulators anyway.
-rw-r--r--linden/indra/llcommon/llthread.cpp35
-rw-r--r--linden/indra/llcommon/llthread.h8
-rw-r--r--linden/indra/newview/lltexturefetch.cpp42
3 files changed, 20 insertions, 65 deletions
diff --git a/linden/indra/llcommon/llthread.cpp b/linden/indra/llcommon/llthread.cpp
index 60ccd5c..692d6c4 100644
--- a/linden/indra/llcommon/llthread.cpp
+++ b/linden/indra/llcommon/llthread.cpp
@@ -283,7 +283,6 @@ LLMutex::LLMutex(apr_pool_t *poolp) :
283 apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp); 283 apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
284} 284}
285 285
286
287LLMutex::~LLMutex() 286LLMutex::~LLMutex()
288{ 287{
289#if _DEBUG 288#if _DEBUG
@@ -297,40 +296,14 @@ LLMutex::~LLMutex()
297 } 296 }
298} 297}
299 298
300
301void LLMutex::lock()
302{
303 apr_thread_mutex_lock(mAPRMutexp);
304}
305
306void LLMutex::unlock()
307{
308 apr_thread_mutex_unlock(mAPRMutexp);
309}
310
311bool LLMutex::isLocked() 299bool LLMutex::isLocked()
312{ 300{
313 apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp); 301 if (!tryLock())
314 if (APR_STATUS_IS_EBUSY(status))
315 { 302 {
316 return true; 303 return true;
317 } 304 }
318 else 305 apr_thread_mutex_unlock(mAPRMutexp);
319 { 306 return false;
320 apr_thread_mutex_unlock(mAPRMutexp);
321 return false;
322 }
323}
324
325//trys to grab a lock and if sucessful returns true
326bool LLMutex::tryLock()
327{
328 apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
329 if (APR_STATUS_IS_EBUSY(status))
330 {
331 return false;
332 }
333 return true;
334} 307}
335 308
336//============================================================================ 309//============================================================================
@@ -343,14 +316,12 @@ LLCondition::LLCondition(apr_pool_t *poolp) :
343 apr_thread_cond_create(&mAPRCondp, mAPRPoolp); 316 apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
344} 317}
345 318
346
347LLCondition::~LLCondition() 319LLCondition::~LLCondition()
348{ 320{
349 apr_thread_cond_destroy(mAPRCondp); 321 apr_thread_cond_destroy(mAPRCondp);
350 mAPRCondp = NULL; 322 mAPRCondp = NULL;
351} 323}
352 324
353
354void LLCondition::wait() 325void LLCondition::wait()
355{ 326{
356 apr_thread_cond_wait(mAPRCondp, mAPRMutexp); 327 apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
diff --git a/linden/indra/llcommon/llthread.h b/linden/indra/llcommon/llthread.h
index d773fa4..ed76a3b 100644
--- a/linden/indra/llcommon/llthread.h
+++ b/linden/indra/llcommon/llthread.h
@@ -131,10 +131,12 @@ public:
131 LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex 131 LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
132 ~LLMutex(); 132 ~LLMutex();
133 133
134 void lock(); // blocks 134 void lock() { apr_thread_mutex_lock(mAPRMutexp); }
135 void unlock(); 135 void unlock() { apr_thread_mutex_unlock(mAPRMutexp); }
136 // Returns true if lock was obtained successfully.
137 bool tryLock() { return !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); }
138
136 bool isLocked(); // non-blocking, but does do a lock/unlock so not free 139 bool isLocked(); // non-blocking, but does do a lock/unlock so not free
137 bool tryLock(); //non-blocking, but not free, returns true if grabed lock
138 140
139protected: 141protected:
140 apr_thread_mutex_t *mAPRMutexp; 142 apr_thread_mutex_t *mAPRMutexp;
diff --git a/linden/indra/newview/lltexturefetch.cpp b/linden/indra/newview/lltexturefetch.cpp
index 3a5665c..62b4c8b 100644
--- a/linden/indra/newview/lltexturefetch.cpp
+++ b/linden/indra/newview/lltexturefetch.cpp
@@ -744,26 +744,17 @@ bool LLTextureFetchWorker::doWork(S32 param)
744 } 744 }
745 else if (mSentRequest == UNSENT) 745 else if (mSentRequest == UNSENT)
746 { 746 {
747 if(mFetcher->mQueueMutex.tryLock()) 747 // Add this to the network queue and sit here.
748 { 748 // LLTextureFetch::update() will send off a request which will change our state
749 // Add this to the network queue and sit here. 749 mRequestedSize = mDesiredSize;
750 // LLTextureFetch::update() will send off a request which will change our state 750 mRequestedDiscard = mDesiredDiscard;
751 mRequestedSize = mDesiredSize; 751 mSentRequest = QUEUED;
752 mRequestedDiscard = mDesiredDiscard; 752 mFetcher->addToNetworkQueue(this);
753 mSentRequest = QUEUED; 753 setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
754 mFetcher->addToNetworkQueue(this);
755 setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
756 mFetcher->mQueueMutex.unlock();
757 }
758 return false; 754 return false;
759 } 755 }
760 else 756 else
761 { 757 {
762 // Shouldn't need to do anything here
763 //llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end());
764 // Make certain this is in the network queue
765 //mFetcher->addToNetworkQueue(this);
766 //setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
767 return false; 758 return false;
768 } 759 }
769 } 760 }
@@ -1473,23 +1464,12 @@ void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
1473 } 1464 }
1474} 1465}
1475 1466
1476// Need to hold mQueueMutex when entering this function SNOW-196
1477// Snowglobe ToDo fix holding mQueueMutex over the entire function, we only need
1478// it for the mRequestMap access
1479// protected 1467// protected
1480void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker) 1468void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker)
1481{ 1469{
1482 bool is_worker_in_request_map = (mRequestMap.find(worker->mID) != mRequestMap.end());
1483
1484 LLMutexLock lock(&mNetworkQueueMutex); 1470 LLMutexLock lock(&mNetworkQueueMutex);
1485 if (is_worker_in_request_map) 1471 mNetworkQueue.insert(worker->mID);
1486 { 1472 for (cancel_queue_t::iterator iter1 = mCancelQueue.begin(); iter1 != mCancelQueue.end(); ++iter1)
1487 // only add to the queue if in the request map
1488 // i.e. a delete has not been requested
1489 mNetworkQueue.insert(worker->mID);
1490 }
1491 for (cancel_queue_t::iterator iter1 = mCancelQueue.begin();
1492 iter1 != mCancelQueue.end(); ++iter1)
1493 { 1473 {
1494 iter1->second.erase(worker->mID); 1474 iter1->second.erase(worker->mID);
1495 } 1475 }
@@ -1715,8 +1695,10 @@ void LLTextureFetch::sendRequestListToSimulators()
1715 LLTextureFetchWorker* req = getWorker(*curiter); 1695 LLTextureFetchWorker* req = getWorker(*curiter);
1716 if (!req) 1696 if (!req)
1717 { 1697 {
1698 // This happens when a request was removed from mRequestMap in a race
1699 // with adding it to mNetworkQueue by doWork (see SNOW-196).
1718 mNetworkQueue.erase(curiter); 1700 mNetworkQueue.erase(curiter);
1719 continue; // paranoia 1701 continue;
1720 } 1702 }
1721 llassert(req->mState == LLTextureFetchWorker::LOAD_FROM_NETWORK || LLTextureFetchWorker::LOAD_FROM_SIMULATOR); 1703 llassert(req->mState == LLTextureFetchWorker::LOAD_FROM_NETWORK || LLTextureFetchWorker::LOAD_FROM_SIMULATOR);
1722 if ((req->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK) && 1704 if ((req->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK) &&