summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2026-02-12 00:37:46 +0200
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2026-02-15 16:11:04 +0200
commitb9fd20501e2cff8831832f00d7ca9fcfc0d9e801 (patch)
treef8f7c3c3f540a14a83c0d0015fd5430bc3b14ec0
parent83b397bfa6bd3932e8a10e8d54b509cff048dbf2 (diff)
#5356 Fix fast texture cache's mutex stall #2
-rw-r--r--indra/newview/llmeshrepository.cpp5
-rw-r--r--indra/newview/lltexturecache.cpp6
-rw-r--r--indra/newview/lltexturecache.h4
-rw-r--r--indra/newview/llviewertexturelist.cpp20
4 files changed, 23 insertions, 12 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index ed342935ad..20bda5039d 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -3331,6 +3331,8 @@ void LLMeshRepoThread::notifyLoadedMeshes()
loaded_queue.swap(mLoadedQ);
mLoadedMutex->unlock();
+ LL_PROFILE_ZONE_NAMED("notify loaded meshes");
+
update_metrics = true;
// Process the elements free of the lock
@@ -3362,6 +3364,8 @@ void LLMeshRepoThread::notifyLoadedMeshes()
unavil_queue.swap(mUnavailableQ);
mLoadedMutex->unlock();
+ LL_PROFILE_ZONE_NAMED("notify unavail meshes");
+
update_metrics = true;
// Process the elements free of the lock
@@ -3380,6 +3384,7 @@ void LLMeshRepoThread::notifyLoadedMeshes()
{
if (mLoadedMutex->trylock())
{
+ LL_PROFILE_ZONE_NAMED("notify misc meshes");
std::deque<LLPointer<LLMeshSkinInfo>> skin_info_q;
std::deque<UUIDBasedRequest> skin_info_unavail_q;
std::list<LLModel::Decomposition*> decomp_q;
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 2e7f353e03..8c8734b52f 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -2048,7 +2048,7 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d
LL_PROFILE_ZONE_NAMED("Read fast cache");
LLMutexLock lock(&mFastCacheMutex);
- openFastCache();
+ openFastCache(); // only reopens if needed, lasts 10 seconds
mFastCachep->seek(APR_SET, offset);
@@ -2079,7 +2079,9 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d
closeFastCache();
}
- LLPointer<LLImageRaw> raw = new LLImageRaw(data, head[0], head[1], head[2], true);
+
+ // directly construct image from new buffer.
+ LLPointer<LLImageRaw> raw = new LLImageRaw(data, head[0], head[1], head[2], true /*take ownership*/);
return raw;
}
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index 42894383fd..a09bcc1572 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -148,7 +148,7 @@ public:
U32 getMaxEntries() { return sCacheMaxEntries; };
bool isInCache(const LLUUID& id) ;
bool isInLocal(const LLUUID& id) ; //not thread safe at the moment
-
+ LLMutex* getFastCacheMutex() { return &mFastCacheMutex; }
protected:
// Accessed by LLTextureCacheWorker
std::string getLocalFileName(const LLUUID& id);
@@ -194,7 +194,7 @@ private:
// Internal
LLMutex mWorkersMutex;
LLMutex mHeaderMutex;
- LLMutex mHeaderIDMapMutex;
+ LLMutex mHeaderIDMapMutex; // To avoid deadlocks, never lock mFastCacheMutex after mHeaderIDMapMutex.
LLMutex mListMutex;
LLMutex mFastCacheMutex;
LLAPRFile* mHeaderAPRFile;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 11ca3098fd..96962bbeae 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1191,15 +1191,19 @@ F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time)
LLTimer timer;
image_list_t::iterator enditer = mFastCacheList.begin();
- for (image_list_t::iterator iter = mFastCacheList.begin();
- iter != mFastCacheList.end();)
{
- image_list_t::iterator curiter = iter++;
- enditer = iter;
- LLViewerFetchedTexture *imagep = *curiter;
- imagep->loadFromFastCache();
- if (timer.getElapsedTimeF32() > max_time)
- break;
+ // prelock fast cache mutex to avoid waiting multiple times.
+ LLMutexLock cache_lock(LLAppViewer::getTextureCache()->getFastCacheMutex());
+ for (image_list_t::iterator iter = mFastCacheList.begin();
+ iter != mFastCacheList.end();)
+ {
+ image_list_t::iterator curiter = iter++;
+ enditer = iter;
+ LLViewerFetchedTexture* imagep = *curiter;
+ imagep->loadFromFastCache();
+ if (timer.getElapsedTimeF32() > max_time)
+ break;
+ }
}
mFastCacheList.erase(mFastCacheList.begin(), enditer);
return timer.getElapsedTimeF32();