diff options
author | Armin Weatherwax | 2010-03-02 14:55:47 +0100 |
---|---|---|
committer | Armin Weatherwax | 2010-03-04 22:38:49 +0100 |
commit | 5cad29e95879a5a08cb1a8dabfff8eda17e55763 (patch) | |
tree | 3122db3e78f243ce7a5053a7d6c7ea5446537059 | |
parent | Robin Cornelius, Aleric Inglewood: SNOW-196 missing mutexes for texture fetch (diff) | |
download | meta-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.cpp | 35 | ||||
-rw-r--r-- | linden/indra/llcommon/llthread.h | 8 | ||||
-rw-r--r-- | linden/indra/newview/lltexturefetch.cpp | 42 |
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 | |||
287 | LLMutex::~LLMutex() | 286 | LLMutex::~LLMutex() |
288 | { | 287 | { |
289 | #if _DEBUG | 288 | #if _DEBUG |
@@ -297,40 +296,14 @@ LLMutex::~LLMutex() | |||
297 | } | 296 | } |
298 | } | 297 | } |
299 | 298 | ||
300 | |||
301 | void LLMutex::lock() | ||
302 | { | ||
303 | apr_thread_mutex_lock(mAPRMutexp); | ||
304 | } | ||
305 | |||
306 | void LLMutex::unlock() | ||
307 | { | ||
308 | apr_thread_mutex_unlock(mAPRMutexp); | ||
309 | } | ||
310 | |||
311 | bool LLMutex::isLocked() | 299 | bool 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 | ||
326 | bool 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 | |||
347 | LLCondition::~LLCondition() | 319 | LLCondition::~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 | |||
354 | void LLCondition::wait() | 325 | void 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 | ||
139 | protected: | 141 | protected: |
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 |
1480 | void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker) | 1468 | void 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) && |