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;
+                    }
                 }
             }