partial fix for EXT-4352. fixed mutex deadlocks and turned on the multi-threaded texture fetching.

meow-7.2.2
Xiaohong Bao 2010-02-08 14:40:06 -08:00
parent ac59a7c130
commit 68ea8e13ac
3 changed files with 86 additions and 42 deletions

View File

@ -1679,7 +1679,7 @@ bool LLAppViewer::initThreads()
// Image decoding
LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && false);
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true);
LLImage::initClass();
if (LLFastTimer::sLog || LLFastTimer::sMetricLog)

View File

@ -73,13 +73,11 @@ private:
}
virtual void completed(bool success)
{
mFetcher->lockQueue();
LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
if (worker)
{
worker->callbackCacheRead(success, mFormattedImage, mImageSize, mImageLocal);
}
mFetcher->unlockQueue();
}
private:
LLTextureFetch* mFetcher;
@ -95,13 +93,11 @@ private:
}
virtual void completed(bool success)
{
mFetcher->lockQueue();
LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
if (worker)
{
worker->callbackCacheWrite(success);
}
mFetcher->unlockQueue();
}
private:
LLTextureFetch* mFetcher;
@ -117,13 +113,11 @@ private:
}
virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux)
{
mFetcher->lockQueue();
LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
if (worker)
{
worker->callbackDecoded(success, raw, aux);
}
mFetcher->unlockQueue();
}
private:
LLTextureFetch* mFetcher;
@ -166,6 +160,8 @@ public:
void setGetStatus(U32 status, const std::string& reason)
{
LLMutexLock lock(&mWorkMutex);
mGetStatus = status;
mGetReason = reason;
}
@ -307,7 +303,6 @@ public:
}
lldebugs << "HTTP COMPLETE: " << mID << llendl;
mFetcher->lockQueue();
LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
if (worker)
{
@ -339,7 +334,6 @@ public:
mFetcher->removeFromHTTPQueue(mID);
llwarns << "Worker not found: " << mID << llendl;
}
mFetcher->unlockQueue();
}
private:
@ -1440,12 +1434,9 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
return false;
}
LLTextureFetchWorker* worker = NULL;
LLMutexLock lock(&mQueueMutex);
map_t::iterator iter = mRequestMap.find(id);
if (iter != mRequestMap.end())
LLTextureFetchWorker* worker = getWorker(id) ;
if (worker)
{
worker = iter->second;
if (worker->mHost != host)
{
llwarns << "LLTextureFetch::createRequest " << id << " called with multiple hosts: "
@ -1494,41 +1485,48 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
return false; // need to wait for previous aborted request to complete
}
worker->lockWorkMutex();
worker->mActiveCount++;
worker->mNeedsAux = needs_aux;
worker->setImagePriority(priority);
worker->setDesiredDiscard(desired_discard, desired_size);
worker->unlockWorkMutex();
if (!worker->haveWork())
{
worker->mState = LLTextureFetchWorker::INIT;
worker->unlockWorkMutex();
worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
}
else
{
worker->unlockWorkMutex();
}
}
else
{
worker = new LLTextureFetchWorker(this, url, id, host, priority, desired_discard, desired_size);
lockQueue() ;
mRequestMap[id] = worker;
}
unlockQueue() ;
worker->lockWorkMutex();
worker->mActiveCount++;
worker->mNeedsAux = needs_aux;
worker->unlockWorkMutex();
}
// llinfos << "REQUESTED: " << id << " Discard: " << desired_discard << llendl;
return true;
}
void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
{
LLMutexLock lock(&mQueueMutex);
LLTextureFetchWorker* worker = getWorker(id);
if (worker)
{
removeRequest(worker, cancel);
}
}
// protected
void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker)
{
lockQueue() ;
bool in_request_map = (mRequestMap.find(worker->mID) != mRequestMap.end()) ;
unlockQueue() ;
LLMutexLock lock(&mNetworkQueueMutex);
if (mRequestMap.find(worker->mID) != mRequestMap.end())
if (in_request_map)
{
// only add to the queue if in the request map
// i.e. a delete has not been requested
@ -1564,10 +1562,34 @@ void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id)
mHTTPTextureQueue.erase(id);
}
// call lockQueue() first!
void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
{
lockQueue() ;
LLTextureFetchWorker* worker = getWorkerAfterLock(id);
if (worker)
{
size_t erased_1 = mRequestMap.erase(worker->mID);
unlockQueue() ;
llassert_always(erased_1 > 0) ;
removeFromNetworkQueue(worker, cancel);
llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ;
worker->scheduleDelete();
}
else
{
unlockQueue() ;
}
}
void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
{
lockQueue() ;
size_t erased_1 = mRequestMap.erase(worker->mID);
unlockQueue() ;
llassert_always(erased_1 > 0) ;
removeFromNetworkQueue(worker, cancel);
llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ;
@ -1575,8 +1597,26 @@ void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
worker->scheduleDelete();
}
S32 LLTextureFetch::getNumRequests()
{
lockQueue() ;
S32 size = (S32)mRequestMap.size();
unlockQueue() ;
return size ;
}
S32 LLTextureFetch::getNumHTTPRequests()
{
mNetworkQueueMutex.lock() ;
S32 size = (S32)mHTTPTextureQueue.size();
mNetworkQueueMutex.unlock() ;
return size ;
}
// call lockQueue() first!
LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id)
LLTextureFetchWorker* LLTextureFetch::getWorkerAfterLock(const LLUUID& id)
{
LLTextureFetchWorker* res = NULL;
map_t::iterator iter = mRequestMap.find(id);
@ -1587,12 +1627,18 @@ LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id)
return res;
}
LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id)
{
LLMutexLock lock(&mQueueMutex) ;
return getWorkerAfterLock(id) ;
}
bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux)
{
bool res = false;
LLMutexLock lock(&mQueueMutex);
LLTextureFetchWorker* worker = getWorker(id);
if (worker)
{
@ -1644,7 +1690,6 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
{
bool res = false;
LLMutexLock lock(&mQueueMutex);
LLTextureFetchWorker* worker = getWorker(id);
if (worker)
{
@ -1760,8 +1805,6 @@ void LLTextureFetch::sendRequestListToSimulators()
}
timer.reset();
LLMutexLock lock(&mQueueMutex);
// Send requests
typedef std::set<LLTextureFetchWorker*,LLTextureFetchWorker::Compare> request_list_t;
typedef std::map< LLHost, request_list_t > work_request_map_t;
@ -1970,7 +2013,6 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes,
U16 data_size, U8* data)
{
LLMutexLock lock(&mQueueMutex);
LLTextureFetchWorker* worker = getWorker(id);
bool res = true;
@ -2003,7 +2045,9 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8
if (!res)
{
++mBadPacketCount;
mNetworkQueueMutex.lock() ;
mCancelQueue[host].insert(id);
mNetworkQueueMutex.unlock() ;
return false;
}
@ -2024,7 +2068,6 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8
bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data)
{
LLMutexLock lock(&mQueueMutex);
LLTextureFetchWorker* worker = getWorker(id);
bool res = true;
@ -2048,7 +2091,9 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1
if (!res)
{
++mBadPacketCount;
mNetworkQueueMutex.lock() ;
mCancelQueue[host].insert(id);
mNetworkQueueMutex.unlock() ;
return false;
}
@ -2088,7 +2133,6 @@ BOOL LLTextureFetch::isFromLocalCache(const LLUUID& id)
{
BOOL from_cache = FALSE ;
LLMutexLock lock(&mQueueMutex);
LLTextureFetchWorker* worker = getWorker(id);
if (worker)
{
@ -2110,7 +2154,6 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r
F32 request_dtime = 999999.f;
U32 fetch_priority = 0;
LLMutexLock lock(&mQueueMutex);
LLTextureFetchWorker* worker = getWorker(id);
if (worker && worker->haveWork())
{

View File

@ -77,13 +77,14 @@ public:
S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p,
U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p);
void dump();
S32 getNumRequests() { return mRequestMap.size(); }
S32 getNumHTTPRequests() { return mHTTPTextureQueue.size(); }
S32 getNumRequests() ;
S32 getNumHTTPRequests() ;
// Public for access by callbacks
void lockQueue() { mQueueMutex.lock(); }
void unlockQueue() { mQueueMutex.unlock(); }
LLTextureFetchWorker* getWorker(const LLUUID& id);
LLTextureFetchWorker* getWorkerAfterLock(const LLUUID& id);
LLTextureInfo* getTextureInfo() { return &mTextureInfo; }
@ -92,7 +93,7 @@ protected:
void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel);
void addToHTTPQueue(const LLUUID& id);
void removeFromHTTPQueue(const LLUUID& id);
S32 getHTTPQueueSize() { return (S32)mHTTPTextureQueue.size(); }
S32 getHTTPQueueSize() { return getNumHTTPRequests(); }
void removeRequest(LLTextureFetchWorker* worker, bool cancel);
// Called from worker thread (during doWork)
void processCurlRequests();
@ -111,8 +112,8 @@ public:
S32 mBadPacketCount;
private:
LLMutex mQueueMutex;
LLMutex mNetworkQueueMutex;
LLMutex mQueueMutex; //to protect mRequestMap only
LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue.
LLTextureCache* mTextureCache;
LLImageDecodeThread* mImageDecodeThread;