summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorXiaohong Bao <bao@lindenlab.com>2010-02-08 14:40:06 -0800
committerXiaohong Bao <bao@lindenlab.com>2010-02-08 14:40:06 -0800
commit68ea8e13aca84da898a8a067c98eb0b8327a8de4 (patch)
treef76d34387fb292df48d7092b8e4d6d6806114b94 /indra
parentac59a7c130f3fcbbb8f228bdf69c44ffa09f07a2 (diff)
partial fix for EXT-4352. fixed mutex deadlocks and turned on the multi-threaded texture fetching.
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/llappviewer.cpp2
-rw-r--r--indra/newview/lltexturefetch.cpp115
-rw-r--r--indra/newview/lltexturefetch.h11
3 files changed, 86 insertions, 42 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 98ec907886..5349ccabec 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -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)
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 404b79bfaf..bdc196e16c 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -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())
{
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 373e38a83c..5213c4f488 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -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;