EGL BlobCache: Synchronize access to deferred write status
Protect access to mDeferredWrites with a mutex. It is updated
by the worker thread upon completion.
Test: pubg_mobile_launch ANGLE trace
Test: /data/nativetest64/EGL_test/EGL_test
Test: /data/nativetest64/libEGL_test/libEGL_test
Bug: b/271975248
Change-Id: Id278f4677a72f2d981a9400ee871bdcc1b0168ef
diff --git a/opengl/libs/EGL/MultifileBlobCache.cpp b/opengl/libs/EGL/MultifileBlobCache.cpp
index 607e214..f1b7a5c 100644
--- a/opengl/libs/EGL/MultifileBlobCache.cpp
+++ b/opengl/libs/EGL/MultifileBlobCache.cpp
@@ -298,13 +298,17 @@
// Sending -1 as the fd indicates we don't have an fd for this
if (!addToHotCache(entryHash, -1, buffer, fileSize)) {
- ALOGE("GET: Failed to add %u to hot cache", entryHash);
+ ALOGE("SET: Failed to add %u to hot cache", entryHash);
return;
}
// Track that we're creating a pending write for this entry
// Include the buffer to handle the case when multiple writes are pending for an entry
- mDeferredWrites.insert(std::make_pair(entryHash, buffer));
+ {
+ // Synchronize access to deferred write status
+ std::lock_guard<std::mutex> lock(mDeferredWriteStatusMutex);
+ mDeferredWrites.insert(std::make_pair(entryHash, buffer));
+ }
// Create deferred task to write to storage
ALOGV("SET: Adding task to queue.");
@@ -371,8 +375,15 @@
} else {
ALOGV("GET: HotCache MISS for entry: %u", entryHash);
- if (mDeferredWrites.find(entryHash) != mDeferredWrites.end()) {
- // Wait for writes to complete if there is an outstanding write for this entry
+ // Wait for writes to complete if there is an outstanding write for this entry
+ bool wait = false;
+ {
+ // Synchronize access to deferred write status
+ std::lock_guard<std::mutex> lock(mDeferredWriteStatusMutex);
+ wait = mDeferredWrites.find(entryHash) != mDeferredWrites.end();
+ }
+
+ if (wait) {
ALOGV("GET: Waiting for write to complete for %u", entryHash);
waitForWorkComplete();
}
@@ -484,6 +495,7 @@
mHotCacheSize, newEntrySize, mHotCacheLimit, newEntryHash);
// Wait for all the files to complete writing so our hot cache is accurate
+ ALOGV("HOTCACHE(ADD): Waiting for work to complete for %u", newEntryHash);
waitForWorkComplete();
// Free up old entries until under the limit
@@ -520,6 +532,7 @@
ALOGV("HOTCACHE(REMOVE): Removing %u from hot cache", entryHash);
// Wait for all the files to complete writing so our hot cache is accurate
+ ALOGV("HOTCACHE(REMOVE): Waiting for work to complete for %u", entryHash);
waitForWorkComplete();
ALOGV("HOTCACHE(REMOVE): Closing hot cache entry for %u", entryHash);
@@ -590,6 +603,7 @@
size_t limit = cacheByteLimit;
// Wait for all deferred writes to complete
+ ALOGV("TRIM: Waiting for work to complete.");
waitForWorkComplete();
size_t size = getTotalSize();
@@ -646,13 +660,18 @@
// Erase the entry from mDeferredWrites
// Since there could be multiple outstanding writes for an entry, find the matching one
- typedef std::multimap<uint32_t, uint8_t*>::iterator entryIter;
- std::pair<entryIter, entryIter> iterPair = mDeferredWrites.equal_range(entryHash);
- for (entryIter it = iterPair.first; it != iterPair.second; ++it) {
- if (it->second == buffer) {
- ALOGV("DEFERRED: Marking write complete for %u at %p", it->first, it->second);
- mDeferredWrites.erase(it);
- break;
+ {
+ // Synchronize access to deferred write status
+ std::lock_guard<std::mutex> lock(mDeferredWriteStatusMutex);
+ typedef std::multimap<uint32_t, uint8_t*>::iterator entryIter;
+ std::pair<entryIter, entryIter> iterPair = mDeferredWrites.equal_range(entryHash);
+ for (entryIter it = iterPair.first; it != iterPair.second; ++it) {
+ if (it->second == buffer) {
+ ALOGV("DEFERRED: Marking write complete for %u at %p", it->first,
+ it->second);
+ mDeferredWrites.erase(it);
+ break;
+ }
}
}