diff options
| author | Monty Brandenberg <monty@lindenlab.com> | 2012-08-19 18:51:21 -0400 | 
|---|---|---|
| committer | Monty Brandenberg <monty@lindenlab.com> | 2012-08-19 18:51:21 -0400 | 
| commit | 4b86f8983ad343b675e3f4960e91f0d4cb876dea (patch) | |
| tree | d48fa2043f0c10afdba55de79d554a66ac488fc1 | |
| parent | d06739facfc13f5e7081783f85c1dd3576c3c155 (diff) | |
SH-3329  Cached scene loads slower than same scene with cleared cache.
A/B comparison with original code showed the newer issuing lower-priority
requests of the cache reader and some other minor changes.  Brought them
into agreement (this is cargo-cult programming).  Made the HTTP resource
semaphore an atomic int for rigorous correctness across threads.  I
swear I'm going to tear down this code someday.
| -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. | 
