diff options
Diffstat (limited to 'indra')
-rwxr-xr-x | indra/newview/lltexturefetch.cpp | 47 | ||||
-rw-r--r-- | indra/newview/lltexturefetch.h | 4 |
2 files changed, 35 insertions, 16 deletions
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 718b15825d..6ae20edb9f 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -439,20 +439,27 @@ private: void lockWorkMutex() { mWorkMutex.lock(); } void unlockWorkMutex() { mWorkMutex.unlock(); } + // Threads: Ttf // Locks: Mw - void acquireHttpSemaphore() + bool acquireHttpSemaphore() { llassert(! mHttpHasResource); + if (mFetcher->mHttpSemaphore <= 0) + { + return false; + } mHttpHasResource = true; - --mFetcher->mHttpSemaphore; + mFetcher->mHttpSemaphore--; + return true; } + // Threads: Ttf // Locks: Mw void releaseHttpSemaphore() { llassert(mHttpHasResource); mHttpHasResource = false; - ++mFetcher->mHttpSemaphore; + mFetcher->mHttpSemaphore++; } private: @@ -901,6 +908,9 @@ LLTextureFetchWorker::~LLTextureFetchWorker() lockWorkMutex(); // +Mw (should be useless) if (mHttpHasResource) { + // Last-chance catchall to recover the resource. Using an + // atomic datatype solely because this can be running in + // another thread. releaseHttpSemaphore(); } if (mHttpActive) @@ -1351,7 +1361,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // // If it looks like we're busy, keep this request here. // Otherwise, advance into the HTTP states. - if (mFetcher->mHttpSemaphore <= 0 || mFetcher->getHttpWaitersCount()) + if (mFetcher->getHttpWaitersCount() || ! acquireHttpSemaphore()) { mState = WAIT_HTTP_RESOURCE2; setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); @@ -1359,9 +1369,8 @@ bool LLTextureFetchWorker::doWork(S32 param) ++mResourceWaitCount; return false; } + mState = SEND_HTTP_REQ; - acquireHttpSemaphore(); - // *NOTE: You must invoke releaseHttpSemaphore() if you transition // to a state other than SEND_HTTP_REQ or WAIT_HTTP_REQ or abort // the request. @@ -1464,6 +1473,8 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == WAIT_HTTP_REQ) { + // *NOTE: As stated above, all transitions out of this state should + // call releaseHttpSemaphore(). if (mLoaded) { S32 cur_size = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0; @@ -1474,6 +1485,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if(mWriteToCacheState == NOT_WRITE) //map tiles { mState = DONE; + releaseHttpSemaphore(); return true; // failed, means no map tile on the empty region. } @@ -1678,7 +1690,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mAuxImage = NULL; llassert_always(mFormattedImage.notNull()); S32 discard = mHaveAllData ? 0 : mLoadedDiscard; - U32 image_priority = LLWorkerThread::PRIORITY_LOW | mWorkPriority; + U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority; mDecoded = FALSE; mState = DECODE_IMAGE_UPDATE; LL_DEBUGS("Texture") << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard @@ -1789,7 +1801,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == DONE) { - if (mDecodedDiscard > 0 && mDesiredDiscard < mDecodedDiscard) + if (mDecodedDiscard >= 0 && mDesiredDiscard < mDecodedDiscard) { // More data was requested, return to INIT mState = INIT; @@ -3373,7 +3385,9 @@ void LLTextureFetch::removeHttpWaiter(const LLUUID & tid) // Locks: -Mw (must not hold any worker when called) void LLTextureFetch::releaseHttpWaiters() { - if (mHttpSemaphore < HTTP_REQUESTS_IN_QUEUE_LOW_WATER) + // Use mHttpSemaphore rather than mHTTPTextureQueue.size() + // to avoid a lock. + if (mHttpSemaphore < (HTTP_REQUESTS_IN_QUEUE_HIGH_WATER - HTTP_REQUESTS_IN_QUEUE_LOW_WATER)) return; // Quickly make a copy of all the LLUIDs. Get off the @@ -3425,22 +3439,27 @@ void LLTextureFetch::releaseHttpWaiters() // with other callers. Do defensive things like getting // refreshed counts of requests and checking if someone else // has moved any worker state around.... - for (worker_list_t::iterator iter2(tids2.begin()); - tids2.end() != iter2 && mHttpSemaphore > 0; - ++iter2) + for (worker_list_t::iterator iter2(tids2.begin()); tids2.end() != iter2; ++iter2) { LLTextureFetchWorker * worker(* iter2); worker->lockWorkMutex(); // +Mw if (LLTextureFetchWorker::WAIT_HTTP_RESOURCE2 != worker->mState) { + // Not in expected state, try the next one worker->unlockWorkMutex(); // -Mw continue; } + if (! worker->acquireHttpSemaphore()) + { + // Out of active slots, quit + worker->unlockWorkMutex(); // -Mw + break; + } + worker->mState = LLTextureFetchWorker::SEND_HTTP_REQ; worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); - worker->acquireHttpSemaphore(); worker->unlockWorkMutex(); // -Mw removeHttpWaiter(worker->mID); @@ -4154,7 +4173,7 @@ S32 LLTextureFetchDebugger::fillCurlQueue() mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS; mNbCurlRequests++; // Hack - if (mNbCurlRequests == 40) + if (mNbCurlRequests == HTTP_REQUESTS_IN_QUEUE_HIGH_WATER) // emulate normal pipeline break; } else diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 95ec8c65c0..4294209f04 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -355,10 +355,10 @@ private: // where it's more expensive to get at them. Requests in either // SEND_HTTP_REQ or WAIT_HTTP_REQ charge against the semaphore // and tracking state transitions is critical to liveness. - int mHttpSemaphore; // Ttf + LLAtomicS32 mHttpSemaphore; // Ttf + Tmain typedef std::set<LLUUID> wait_http_res_queue_t; - wait_http_res_queue_t mHttpWaitResource; // Mfnq + wait_http_res_queue_t mHttpWaitResource; // Mfnq // Cumulative stats on the states/requests issued by // textures running through here. |