Add thread safety annotations for SkMutex

Introduce SkAutoMutexExclusive for SkMutex RAII.

Unsubclass SkMutex from SkBaseMutex to allow annotations
for class field mutexes separate from global mutexes.

Leave SkAutoMutexAcquire for handling global mutexes using
SkBaseMutex.

Test using GrSingleOwner.h.

Change-Id: I19d9d0ae0d05206cbb6ef137dc362969048c9c07
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/213136
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/include/private/GrSingleOwner.h b/include/private/GrSingleOwner.h
index 45818a1..6369ae8 100644
--- a/include/private/GrSingleOwner.h
+++ b/include/private/GrSingleOwner.h
@@ -28,7 +28,7 @@
 
 private:
      void enter() {
-         SkAutoMutexAcquire lock(fMutex);
+         SkAutoMutexExclusive lock(fMutex);
          SkThreadID self = SkGetThreadID();
          SkASSERT(fOwner == self || fOwner == kIllegalThreadID);
          fReentranceCount++;
@@ -36,7 +36,7 @@
      }
 
      void exit() {
-         SkAutoMutexAcquire lock(fMutex);
+         SkAutoMutexExclusive lock(fMutex);
          SkASSERT(fOwner == SkGetThreadID());
          fReentranceCount--;
          if (fReentranceCount == 0) {
@@ -45,8 +45,8 @@
      }
 
      SkMutex fMutex;
-     SkThreadID fOwner;    // guarded by fMutex
-     int fReentranceCount; // guarded by fMutex
+     SkThreadID fOwner    SK_GUARDED_BY(fMutex);
+     int fReentranceCount SK_GUARDED_BY(fMutex);
 };
 #else
 class GrSingleOwner {}; // Provide a dummy implementation so we can pass pointers to constructors
diff --git a/include/private/SkMessageBus.h b/include/private/SkMessageBus.h
index e1b4605..2a40b28 100644
--- a/include/private/SkMessageBus.h
+++ b/include/private/SkMessageBus.h
@@ -74,7 +74,7 @@
 SkMessageBus<Message>::Inbox::Inbox(uint32_t uniqueID) : fUniqueID(uniqueID) {
     // Register ourselves with the corresponding message bus.
     SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();
-    SkAutoMutexAcquire lock(bus->fInboxesMutex);
+    SkAutoMutexExclusive lock(bus->fInboxesMutex);
     bus->fInboxes.push_back(this);
 }
 
@@ -82,7 +82,7 @@
 SkMessageBus<Message>::Inbox::~Inbox() {
     // Remove ourselves from the corresponding message bus.
     SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();
-    SkAutoMutexAcquire lock(bus->fInboxesMutex);
+    SkAutoMutexExclusive lock(bus->fInboxesMutex);
     // This is a cheaper fInboxes.remove(fInboxes.find(this)) when order doesn't matter.
     for (int i = 0; i < bus->fInboxes.count(); i++) {
         if (this == bus->fInboxes[i]) {
@@ -94,7 +94,7 @@
 
 template<typename Message>
 void SkMessageBus<Message>::Inbox::receive(const Message& m) {
-    SkAutoMutexAcquire lock(fMessagesMutex);
+    SkAutoMutexExclusive lock(fMessagesMutex);
     fMessages.push_back(m);
 }
 
@@ -102,7 +102,7 @@
 void SkMessageBus<Message>::Inbox::poll(SkTArray<Message>* messages) {
     SkASSERT(messages);
     messages->reset();
-    SkAutoMutexAcquire lock(fMessagesMutex);
+    SkAutoMutexExclusive lock(fMessagesMutex);
     fMessages.swap(*messages);
 }
 
@@ -114,7 +114,7 @@
 template <typename Message>
 /*static*/ void SkMessageBus<Message>::Post(const Message& m) {
     SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();
-    SkAutoMutexAcquire lock(bus->fInboxesMutex);
+    SkAutoMutexExclusive lock(bus->fInboxesMutex);
     for (int i = 0; i < bus->fInboxes.count(); i++) {
         if (SkShouldPostMessageToBus(m, bus->fInboxes[i]->fUniqueID)) {
             bus->fInboxes[i]->receive(m);
diff --git a/include/private/SkMutex.h b/include/private/SkMutex.h
index 633383b..cb7ad7a 100644
--- a/include/private/SkMutex.h
+++ b/include/private/SkMutex.h
@@ -11,6 +11,7 @@
 #include "include/core/SkTypes.h"
 #include "include/private/SkMacros.h"
 #include "include/private/SkSemaphore.h"
+#include "include/private/SkThreadAnnotations.h"
 #include "include/private/SkThreadID.h"
 
 #define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name;
@@ -39,10 +40,28 @@
     SkDEBUGCODE(SkThreadID fOwner{kIllegalThreadID};)
 };
 
-class SkMutex : public SkBaseMutex {
+class SK_CAPABILITY("mutex") SkMutex {
 public:
-    using SkBaseMutex::SkBaseMutex;
-    ~SkMutex() { fSemaphore.cleanup(); }
+    constexpr SkMutex() = default;
+
+    void acquire() SK_ACQUIRE() {
+        fSemaphore.wait();
+        SkDEBUGCODE(fOwner = SkGetThreadID();)
+    }
+
+    void release() SK_RELEASE_CAPABILITY() {
+        this->assertHeld();
+        SkDEBUGCODE(fOwner = kIllegalThreadID;)
+        fSemaphore.signal();
+    }
+
+    void assertHeld() SK_ASSERT_CAPABILITY(this) {
+        SkASSERT(fOwner == SkGetThreadID());
+    }
+
+private:
+    SkSemaphore fSemaphore{1};
+    SkDEBUGCODE(SkThreadID fOwner{kIllegalThreadID};)
 };
 
 class SkAutoMutexAcquire {
@@ -73,22 +92,15 @@
 };
 #define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire)
 
-// SkAutoExclusive is a lighter weight version of SkAutoMutexAcquire.
-// It assumes that there is a valid mutex, obviating the null check.
-class SkAutoExclusive {
+class SK_SCOPED_CAPABILITY SkAutoMutexExclusive {
 public:
-    template <typename T>
-    SkAutoExclusive(T& mutex) : fMutex(&mutex) {
-        mutex.acquire();
-
-        fRelease = [](void* mutex) { ((T*)mutex)->release(); };
-    }
-    ~SkAutoExclusive() { fRelease(fMutex); }
+    SkAutoMutexExclusive(SkMutex& mutex) SK_ACQUIRE(mutex) : fMutex(mutex) { fMutex.acquire(); }
+    ~SkAutoMutexExclusive() SK_RELEASE_CAPABILITY() { fMutex.release(); }
 
 private:
-    void* fMutex;
-    void (*fRelease)(void*);
+    SkMutex& fMutex;
 };
-#define SkAutoExclusive(...) SK_REQUIRE_LOCAL_VAR(SkAutoExclusive)
+
+#define SkAutoMutexExclusive(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexExclusive)
 
 #endif//SkMutex_DEFINED
diff --git a/include/private/SkThreadAnnotations.h b/include/private/SkThreadAnnotations.h
index 5c01d77..fd312b5 100644
--- a/include/private/SkThreadAnnotations.h
+++ b/include/private/SkThreadAnnotations.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 Google Inc.
+ * Copyright 2019 Google LLC
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
diff --git a/src/codec/SkRawCodec.cpp b/src/codec/SkRawCodec.cpp
index 2503270..f8dff7a 100644
--- a/src/codec/SkRawCodec.cpp
+++ b/src/codec/SkRawCodec.cpp
@@ -113,10 +113,10 @@
                 try {
                     task.ProcessOnThread(taskIndex, taskAreas[taskIndex], tileSize, this->Sniffer());
                 } catch (dng_exception& exception) {
-                    SkAutoMutexAcquire lock(mutex);
+                    SkAutoMutexExclusive lock(mutex);
                     exceptions.push_back(exception);
                 } catch (...) {
-                    SkAutoMutexAcquire lock(mutex);
+                    SkAutoMutexExclusive lock(mutex);
                     exceptions.push_back(dng_exception(dng_error_unknown));
                 }
             });
diff --git a/src/core/SkBitmapCache.cpp b/src/core/SkBitmapCache.cpp
index f29e6fc..c06e9df 100644
--- a/src/core/SkBitmapCache.cpp
+++ b/src/core/SkBitmapCache.cpp
@@ -91,7 +91,7 @@
         return sizeof(fKey) + fInfo.computeByteSize(fRowBytes);
     }
     bool canBePurged() override {
-        SkAutoMutexAcquire ama(fMutex);
+        SkAutoMutexExclusive ama(fMutex);
         return fExternalCounter == 0;
     }
     void postAddInstall(void* payload) override {
@@ -105,7 +105,7 @@
 
     static void ReleaseProc(void* addr, void* ctx) {
         Rec* rec = static_cast<Rec*>(ctx);
-        SkAutoMutexAcquire ama(rec->fMutex);
+        SkAutoMutexExclusive ama(rec->fMutex);
 
         SkASSERT(rec->fExternalCounter > 0);
         rec->fExternalCounter -= 1;
@@ -121,7 +121,7 @@
     }
 
     bool install(SkBitmap* bitmap) {
-        SkAutoMutexAcquire ama(fMutex);
+        SkAutoMutexExclusive ama(fMutex);
 
         if (!fDM && !fMalloc) {
             return false;
diff --git a/src/core/SkExecutor.cpp b/src/core/SkExecutor.cpp
index ab01fb9..1812d30 100644
--- a/src/core/SkExecutor.cpp
+++ b/src/core/SkExecutor.cpp
@@ -93,7 +93,7 @@
     virtual void add(std::function<void(void)> work) override {
         // Add some work to our pile of work to do.
         {
-            SkAutoExclusive lock(fWorkLock);
+            SkAutoMutexExclusive lock(fWorkLock);
             fWork.emplace_back(std::move(work));
         }
         // Tell the Loop() threads to pick it up.
@@ -112,7 +112,7 @@
     bool do_work() {
         std::function<void(void)> work;
         {
-            SkAutoExclusive lock(fWorkLock);
+            SkAutoMutexExclusive lock(fWorkLock);
             SkASSERT(!fWork.empty());        // TODO: if (fWork.empty()) { return true; } ?
             work = pop(&fWork);
         }
diff --git a/src/core/SkImageFilterCache.cpp b/src/core/SkImageFilterCache.cpp
index 6a7bc2b..e851f46 100644
--- a/src/core/SkImageFilterCache.cpp
+++ b/src/core/SkImageFilterCache.cpp
@@ -58,7 +58,7 @@
     };
 
     sk_sp<SkSpecialImage> get(const Key& key, SkIPoint* offset) const override {
-        SkAutoMutexAcquire mutex(fMutex);
+        SkAutoMutexExclusive mutex(fMutex);
         if (Value* v = fLookup.find(key)) {
             *offset = v->fOffset;
             if (v != fLRU.head()) {
@@ -71,7 +71,7 @@
     }
 
     void set(const Key& key, SkSpecialImage* image, const SkIPoint& offset, const SkImageFilter* filter) override {
-        SkAutoMutexAcquire mutex(fMutex);
+        SkAutoMutexExclusive mutex(fMutex);
         if (Value* v = fLookup.find(key)) {
             this->removeInternal(v);
         }
@@ -96,7 +96,7 @@
     }
 
     void purge() override {
-        SkAutoMutexAcquire mutex(fMutex);
+        SkAutoMutexExclusive mutex(fMutex);
         while (fCurrentBytes > 0) {
             Value* tail = fLRU.tail();
             SkASSERT(tail);
@@ -105,7 +105,7 @@
     }
 
     void purgeByImageFilter(const SkImageFilter* filter) override {
-        SkAutoMutexAcquire mutex(fMutex);
+        SkAutoMutexExclusive mutex(fMutex);
         auto* values = fImageFilterValues.find(filter);
         if (!values) {
             return;
diff --git a/src/core/SkPathRef.cpp b/src/core/SkPathRef.cpp
index 0421dac..400d323 100644
--- a/src/core/SkPathRef.cpp
+++ b/src/core/SkPathRef.cpp
@@ -713,7 +713,7 @@
         return;
     }
 
-    SkAutoMutexAcquire lock(fGenIDChangeListenersMutex);
+    SkAutoMutexExclusive lock(fGenIDChangeListenersMutex);
 
     // Clean out any stale listeners before we append the new one.
     for (int i = 0; i < fGenIDChangeListeners.count(); ++i) {
@@ -729,7 +729,7 @@
 
 // we need to be called *before* the genID gets changed or zerod
 void SkPathRef::callGenIDChangeListeners() {
-    SkAutoMutexAcquire lock(fGenIDChangeListenersMutex);
+    SkAutoMutexExclusive lock(fGenIDChangeListenersMutex);
     for (GenIDChangeListener* listener : fGenIDChangeListeners) {
         if (!listener->shouldUnregisterFromPath()) {
             listener->onChange();
diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp
index 522e188..585e3c9 100644
--- a/src/core/SkPixelRef.cpp
+++ b/src/core/SkPixelRef.cpp
@@ -77,13 +77,13 @@
         delete listener;
         return;
     }
-    SkAutoMutexAcquire lock(fGenIDChangeListenersMutex);
+    SkAutoMutexExclusive lock(fGenIDChangeListenersMutex);
     *fGenIDChangeListeners.append() = listener;
 }
 
 // we need to be called *before* the genID gets changed or zerod
 void SkPixelRef::callGenIDChangeListeners() {
-    SkAutoMutexAcquire lock(fGenIDChangeListenersMutex);
+    SkAutoMutexExclusive lock(fGenIDChangeListenersMutex);
     // We don't invalidate ourselves if we think another SkPixelRef is sharing our genID.
     if (this->genIDIsUnique()) {
         for (int i = 0; i < fGenIDChangeListeners.count(); i++) {
diff --git a/src/core/SkSharedMutex.cpp b/src/core/SkSharedMutex.cpp
index 4dd801c..01445d5 100644
--- a/src/core/SkSharedMutex.cpp
+++ b/src/core/SkSharedMutex.cpp
@@ -129,7 +129,7 @@
         int currentSharedCount;
         int waitingExclusiveCount;
         {
-            SkAutoMutexAcquire l(&fMu);
+            SkAutoMutexExclusive l(fMu);
 
             SkASSERTF(!fCurrentShared->find(threadID),
                       "Thread %lx already has an shared lock\n", threadID);
@@ -159,7 +159,7 @@
         int exclusiveWaitingCount;
         int sharedQueueSelect;
         {
-            SkAutoMutexAcquire l(&fMu);
+            SkAutoMutexExclusive l(fMu);
             SkASSERT(0 == fCurrentShared->count());
             if (!fWaitingExclusive->tryRemove(threadID)) {
                 SkDEBUGFAILF("Thread %lx did not have the lock held.\n", threadID);
@@ -182,7 +182,7 @@
 
     void SkSharedMutex::assertHeld() const {
         SkThreadID threadID(SkGetThreadID());
-        SkAutoMutexAcquire l(&fMu);
+        SkAutoMutexExclusive l(fMu);
         SkASSERT(0 == fCurrentShared->count());
         SkASSERT(fWaitingExclusive->find(threadID));
     }
@@ -192,7 +192,7 @@
         int exclusiveWaitingCount;
         int sharedQueueSelect;
         {
-            SkAutoMutexAcquire l(&fMu);
+            SkAutoMutexExclusive l(fMu);
             exclusiveWaitingCount = fWaitingExclusive->count();
             if (exclusiveWaitingCount > 0) {
                 if (!fWaitingShared->tryAdd(threadID)) {
@@ -220,7 +220,7 @@
         int currentSharedCount;
         int waitingExclusiveCount;
         {
-            SkAutoMutexAcquire l(&fMu);
+            SkAutoMutexExclusive l(fMu);
             if (!fCurrentShared->tryRemove(threadID)) {
                 SkDEBUGFAILF("Thread %lx does not hold a shared lock.\n", threadID);
             }
@@ -235,7 +235,7 @@
 
     void SkSharedMutex::assertHeldShared() const {
         SkThreadID threadID(SkGetThreadID());
-        SkAutoMutexAcquire l(&fMu);
+        SkAutoMutexExclusive l(fMu);
         SkASSERT(fCurrentShared->find(threadID));
     }
 
diff --git a/src/fonts/SkFontMgr_indirect.cpp b/src/fonts/SkFontMgr_indirect.cpp
index af53215..b7f4d19 100644
--- a/src/fonts/SkFontMgr_indirect.cpp
+++ b/src/fonts/SkFontMgr_indirect.cpp
@@ -81,7 +81,7 @@
         return nullptr;
     }
 
-    SkAutoMutexAcquire ama(fDataCacheMutex);
+    SkAutoMutexExclusive ama(fDataCacheMutex);
 
     sk_sp<SkTypeface> dataTypeface;
     int dataTypefaceIndex = 0;
diff --git a/src/gpu/gradients/GrGradientBitmapCache.cpp b/src/gpu/gradients/GrGradientBitmapCache.cpp
index da3bef7..fdbc0fc 100644
--- a/src/gpu/gradients/GrGradientBitmapCache.cpp
+++ b/src/gpu/gradients/GrGradientBitmapCache.cpp
@@ -198,7 +198,7 @@
     ///////////////////////////////////
 
     // acquire lock for checking/adding to cache
-    SkAutoExclusive ama(fMutex);
+    SkAutoMutexExclusive ama(fMutex);
     size_t size = keyCount * sizeof(int32_t);
     if (!this->find(storage.get(), size, bitmap)) {
         SkImageInfo info = SkImageInfo::Make(fResolution, 1, colorType, alphaType);
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index 9cc2eb9..fb88cc4 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -117,7 +117,7 @@
 
 private:
     const sk_sp<SharedGenerator>& fSharedGenerator;
-    SkAutoExclusive               fAutoAquire;
+    SkAutoMutexExclusive          fAutoAquire;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -263,7 +263,7 @@
 sk_sp<SkImage> SkImage_Lazy::onMakeColorTypeAndColorSpace(GrRecordingContext*,
                                                           SkColorType targetCT,
                                                           sk_sp<SkColorSpace> targetCS) const {
-    SkAutoExclusive autoAquire(fOnMakeColorTypeAndSpaceMutex);
+    SkAutoMutexExclusive autoAquire(fOnMakeColorTypeAndSpaceMutex);
     if (fOnMakeColorTypeAndSpaceResult &&
         targetCT == fOnMakeColorTypeAndSpaceResult->colorType() &&
         SkColorSpace::Equals(targetCS.get(), fOnMakeColorTypeAndSpaceResult->colorSpace())) {
diff --git a/src/lazy/SkDiscardableMemoryPool.cpp b/src/lazy/SkDiscardableMemoryPool.cpp
index 8d5b627..fa68e49 100644
--- a/src/lazy/SkDiscardableMemoryPool.cpp
+++ b/src/lazy/SkDiscardableMemoryPool.cpp
@@ -169,7 +169,7 @@
         return nullptr;
     }
     auto dm = skstd::make_unique<PoolDiscardableMemory>(sk_ref_sp(this), std::move(addr), bytes);
-    SkAutoMutexAcquire autoMutexAcquire(fMutex);
+    SkAutoMutexExclusive autoMutexAcquire(fMutex);
     fList.addToHead(dm.get());
     fUsed += bytes;
     this->dumpDownTo(fBudget);
@@ -177,7 +177,7 @@
 }
 
 void DiscardableMemoryPool::removeFromPool(PoolDiscardableMemory* dm) {
-    SkAutoMutexAcquire autoMutexAcquire(fMutex);
+    SkAutoMutexExclusive autoMutexAcquire(fMutex);
     // This is called by dm's destructor.
     if (dm->fPointer != nullptr) {
         SkASSERT(fUsed >= dm->fBytes);
@@ -190,7 +190,7 @@
 
 bool DiscardableMemoryPool::lock(PoolDiscardableMemory* dm) {
     SkASSERT(dm != nullptr);
-    SkAutoMutexAcquire autoMutexAcquire(fMutex);
+    SkAutoMutexExclusive autoMutexAcquire(fMutex);
     if (nullptr == dm->fPointer) {
         // May have been purged while waiting for lock.
         #if SK_LAZY_CACHE_STATS
@@ -209,7 +209,7 @@
 
 void DiscardableMemoryPool::unlock(PoolDiscardableMemory* dm) {
     SkASSERT(dm != nullptr);
-    SkAutoMutexAcquire autoMutexAcquire(fMutex);
+    SkAutoMutexExclusive autoMutexAcquire(fMutex);
     dm->fLocked = false;
     this->dumpDownTo(fBudget);
 }
@@ -218,12 +218,12 @@
     return fUsed;
 }
 void DiscardableMemoryPool::setRAMBudget(size_t budget) {
-    SkAutoMutexAcquire autoMutexAcquire(fMutex);
+    SkAutoMutexExclusive autoMutexAcquire(fMutex);
     fBudget = budget;
     this->dumpDownTo(fBudget);
 }
 void DiscardableMemoryPool::dumpPool() {
-    SkAutoMutexAcquire autoMutexAcquire(fMutex);
+    SkAutoMutexExclusive autoMutexAcquire(fMutex);
     this->dumpDownTo(0);
 }
 
diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp
index 377dc59..abf3015 100644
--- a/src/pdf/SkPDFDocument.cpp
+++ b/src/pdf/SkPDFDocument.cpp
@@ -206,20 +206,19 @@
 }
 
 SkPDFIndirectReference SkPDFDocument::emit(const SkPDFObject& object, SkPDFIndirectReference ref){
+    SkAutoMutexExclusive lock(fMutex);
     object.emitObject(this->beginObject(ref));
     this->endObject();
     return ref;
 }
 
-SkWStream* SkPDFDocument::beginObject(SkPDFIndirectReference ref) {
-    fMutex.acquire();
+SkWStream* SkPDFDocument::beginObject(SkPDFIndirectReference ref) SK_REQUIRES(fMutex) {
     begin_indirect_object(&fOffsetMap, ref, this->getStream());
     return this->getStream();
 };
 
-void SkPDFDocument::endObject() {
+void SkPDFDocument::endObject() SK_REQUIRES(fMutex) {
     end_indirect_object(this->getStream());
-    fMutex.release();
 };
 
 static SkSize operator*(SkISize u, SkScalar s) { return SkSize{u.width() * s, u.height() * s}; }
@@ -230,7 +229,7 @@
     if (fPages.empty()) {
         // if this is the first page if the document.
         {
-            SkAutoMutexAcquire autoMutexAcquire(fMutex);
+            SkAutoMutexExclusive autoMutexAcquire(fMutex);
             serializeHeader(&fOffsetMap, this->getStream());
 
         }
@@ -557,7 +556,7 @@
 
     this->waitForJobs();
     {
-        SkAutoMutexAcquire autoMutexAcquire(fMutex);
+        SkAutoMutexExclusive autoMutexAcquire(fMutex);
         serialize_footer(fOffsetMap, this->getStream(), fInfoDict, docCatalogRef, fUUID);
     }
 }
diff --git a/src/pdf/SkPDFDocumentPriv.h b/src/pdf/SkPDFDocumentPriv.h
index 9ab2fab..ab2a62e 100644
--- a/src/pdf/SkPDFDocumentPriv.h
+++ b/src/pdf/SkPDFDocumentPriv.h
@@ -80,6 +80,7 @@
 
     template <typename T>
     void emitStream(const SkPDFDict& dict, T writeStream, SkPDFIndirectReference ref) {
+        SkAutoMutexExclusive lock(fMutex);
         SkWStream* stream = this->beginObject(ref);
         dict.emitObject(stream);
         stream->writeText(" stream\n");
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index c0d0d3c..014efa4 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -1576,7 +1576,7 @@
     // can be very slow. If we do need to compute a new glyphID, then
     // access those freetype objects and continue the loop.
 
-    SkAutoMutexAcquire ama(fC2GCacheMutex);
+    SkAutoMutexExclusive ama(fC2GCacheMutex);
 
     int i;
     for (i = 0; i < count; ++i) {
@@ -1824,7 +1824,7 @@
 }
 
 bool SkTypeface_FreeType::Scanner::recognizedFont(SkStreamAsset* stream, int* numFaces) const {
-    SkAutoMutexAcquire libraryLock(fLibraryMutex);
+    SkAutoMutexExclusive libraryLock(fLibraryMutex);
 
     FT_StreamRec streamRec;
     FT_Face face = this->openFace(stream, -1, &streamRec);
@@ -1843,7 +1843,7 @@
     SkStreamAsset* stream, int ttcIndex,
     SkString* name, SkFontStyle* style, bool* isFixedPitch, AxisDefinitions* axes) const
 {
-    SkAutoMutexAcquire libraryLock(fLibraryMutex);
+    SkAutoMutexExclusive libraryLock(fLibraryMutex);
 
     FT_StreamRec streamRec;
     FT_Face face = this->openFace(stream, ttcIndex, &streamRec);
diff --git a/src/ports/SkFontMgr_FontConfigInterface.cpp b/src/ports/SkFontMgr_FontConfigInterface.cpp
index 52dba25..cdb5460 100644
--- a/src/ports/SkFontMgr_FontConfigInterface.cpp
+++ b/src/ports/SkFontMgr_FontConfigInterface.cpp
@@ -193,7 +193,7 @@
     SkTypeface* onMatchFamilyStyle(const char requestedFamilyName[],
                                    const SkFontStyle& requestedStyle) const override
     {
-        SkAutoMutexAcquire ama(fMutex);
+        SkAutoMutexExclusive ama(fMutex);
 
         SkFontConfigInterface::FontIdentity identity;
         SkString outFamilyName;
@@ -294,7 +294,7 @@
     sk_sp<SkTypeface> onLegacyMakeTypeface(const char requestedFamilyName[],
                                            SkFontStyle requestedStyle) const override
     {
-        SkAutoMutexAcquire ama(fMutex);
+        SkAutoMutexExclusive ama(fMutex);
 
         // Check if this request is already in the request cache.
         using Request = SkFontRequestCache::Request;
diff --git a/src/ports/SkFontMgr_fontconfig.cpp b/src/ports/SkFontMgr_fontconfig.cpp
index 3355e5c..55dfb93 100644
--- a/src/ports/SkFontMgr_fontconfig.cpp
+++ b/src/ports/SkFontMgr_fontconfig.cpp
@@ -699,7 +699,7 @@
      */
     sk_sp<SkTypeface> createTypefaceFromFcPattern(FcPattern* pattern) const {
         FCLocker::AssertHeld();
-        SkAutoMutexAcquire ama(fTFCacheMutex);
+        SkAutoMutexExclusive ama(fTFCacheMutex);
         sk_sp<SkTypeface> face = fTFCache.findByProcAndRef(FindByFcPattern, pattern);
         if (!face) {
             FcPatternReference(pattern);
diff --git a/src/ports/SkFontMgr_fuchsia.cpp b/src/ports/SkFontMgr_fuchsia.cpp
index e3edbc5..05f95cf 100644
--- a/src/ports/SkFontMgr_fuchsia.cpp
+++ b/src/ports/SkFontMgr_fuchsia.cpp
@@ -388,7 +388,7 @@
 
 sk_sp<SkTypeface> SkFontMgr_Fuchsia::GetOrCreateTypeface(TypefaceId id,
                                                          const fuchsia::mem::Buffer& buffer) const {
-    SkAutoMutexAcquire mutexLock(fCacheMutex);
+    SkAutoMutexExclusive mutexLock(fCacheMutex);
 
     sk_sp<SkTypeface> cached = fTypefaceCache.findByProcAndRef(FindByTypefaceId, &id);
     if (cached) return cached;
diff --git a/src/ports/SkFontMgr_win_dw.cpp b/src/ports/SkFontMgr_win_dw.cpp
index 33d7e5d..f7bce89 100644
--- a/src/ports/SkFontMgr_win_dw.cpp
+++ b/src/ports/SkFontMgr_win_dw.cpp
@@ -458,7 +458,7 @@
         IDWriteFontFace* fontFace,
         IDWriteFont* font,
         IDWriteFontFamily* fontFamily) const {
-    SkAutoMutexAcquire ama(fTFCacheMutex);
+    SkAutoMutexExclusive ama(fTFCacheMutex);
     ProtoDWriteTypeface spec = { fontFace, font, fontFamily };
     sk_sp<SkTypeface> face = fTFCache.findByProcAndRef(FindByDWriteFont, &spec);
     if (nullptr == face) {
diff --git a/src/ports/SkRemotableFontMgr_win_dw.cpp b/src/ports/SkRemotableFontMgr_win_dw.cpp
index 64f0638..85f8b02 100644
--- a/src/ports/SkRemotableFontMgr_win_dw.cpp
+++ b/src/ports/SkRemotableFontMgr_win_dw.cpp
@@ -58,7 +58,7 @@
                    "Failed to re-convert to IDWriteFontFileLoader.",
                    SkFontIdentity::kInvalidDataId);
 
-        SkAutoMutexAcquire ama(fDataIdCacheMutex);
+        SkAutoMutexExclusive ama(fDataIdCacheMutex);
         int count = fDataIdCache.count();
         int i;
         for (i = 0; i < count; ++i) {
@@ -417,7 +417,7 @@
     }
 
     SkStreamAsset* getData(int dataId) const override {
-        SkAutoMutexAcquire ama(fDataIdCacheMutex);
+        SkAutoMutexExclusive ama(fDataIdCacheMutex);
         if (dataId >= fDataIdCache.count()) {
             return nullptr;
         }
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp
index 432356a..22d06fb 100644
--- a/src/ports/SkScalerContext_win_dw.cpp
+++ b/src/ports/SkScalerContext_win_dw.cpp
@@ -52,7 +52,7 @@
 }
 
 static bool is_hinted(DWriteFontTypeface* typeface) {
-    SkAutoExclusive l(DWriteFactoryMutex);
+    SkAutoMutexAcquire l(DWriteFactoryMutex);
     AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get());
     if (!maxp.fExists) {
         return false;
@@ -123,7 +123,7 @@
 }
 
 static bool has_bitmap_strike(DWriteFontTypeface* typeface, GaspRange range) {
-    SkAutoExclusive l(DWriteFactoryMutex);
+    SkAutoMutexAcquire l(DWriteFactoryMutex);
     {
         AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get());
         if (!eblc.fExists) {
@@ -384,7 +384,7 @@
     if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
         DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
     {
-        SkAutoExclusive l(DWriteFactoryMutex);
+        SkAutoMutexAcquire l(DWriteFactoryMutex);
         HRBM(this->getDWriteTypeface()->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
                  fTextSizeMeasure,
                  1.0f, // pixelsPerDip
@@ -396,7 +396,7 @@
                  &gm),
              "Could not get gdi compatible glyph metrics.");
     } else {
-        SkAutoExclusive l(DWriteFactoryMutex);
+        SkAutoMutexAcquire l(DWriteFactoryMutex);
         HRBM(this->getDWriteTypeface()->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
              "Could not get design metrics.");
     }
@@ -452,7 +452,7 @@
 
     SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
     {
-        SkAutoExclusive l(DWriteFactoryMutex);
+        SkAutoMutexAcquire l(DWriteFactoryMutex);
         // IDWriteFactory2::CreateGlyphRunAnalysis is very bad at aliased glyphs.
         if (this->getDWriteTypeface()->fFactory2 &&
                 (fGridFitMode == DWRITE_GRID_FIT_MODE_DISABLED ||
@@ -575,7 +575,7 @@
         HRVM(SkDWriteGeometrySink::Create(&path, &geometryToPath),
             "Could not create geometry to path converter.");
         {
-            SkAutoExclusive l(DWriteFactoryMutex);
+            SkAutoMutexAcquire l(DWriteFactoryMutex);
             HRVM(colorGlyph->glyphRun.fontFace->GetGlyphRunOutline(
                     colorGlyph->glyphRun.fontEmSize,
                     colorGlyph->glyphRun.glyphIndices,
@@ -927,7 +927,7 @@
     {
         SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
         {
-            SkAutoExclusive l(DWriteFactoryMutex);
+            SkAutoMutexAcquire l(DWriteFactoryMutex);
             // IDWriteFactory2::CreateGlyphRunAnalysis is very bad at aliased glyphs.
             if (this->getDWriteTypeface()->fFactory2 &&
                     (fGridFitMode == DWRITE_GRID_FIT_MODE_DISABLED ||
@@ -1027,7 +1027,7 @@
         HRVM(SkDWriteGeometrySink::Create(&path, &geometryToPath),
              "Could not create geometry to path converter.");
         {
-            SkAutoExclusive l(DWriteFactoryMutex);
+            SkAutoMutexAcquire l(DWriteFactoryMutex);
             HRVM(colorGlyph->glyphRun.fontFace->GetGlyphRunOutline(
                 colorGlyph->glyphRun.fontEmSize,
                 colorGlyph->glyphRun.glyphIndices,
@@ -1162,7 +1162,7 @@
          "Could not create geometry to path converter.");
     UINT16 glyphId = SkTo<UINT16>(glyph);
     {
-        SkAutoExclusive l(DWriteFactoryMutex);
+        SkAutoMutexAcquire l(DWriteFactoryMutex);
         //TODO: convert to<->from DIUs? This would make a difference if hinting.
         //It may not be needed, it appears that DirectWrite only hints at em size.
         HRBM(this->getDWriteTypeface()->fDWriteFontFace->GetGlyphRunOutline(
diff --git a/src/utils/win/SkDWriteFontFileStream.cpp b/src/utils/win/SkDWriteFontFileStream.cpp
index a739c31..8c102cf 100644
--- a/src/utils/win/SkDWriteFontFileStream.cpp
+++ b/src/utils/win/SkDWriteFontFileStream.cpp
@@ -198,7 +198,7 @@
 
     } else {
         // May be called from multiple threads.
-        SkAutoMutexAcquire ama(fStreamMutex);
+        SkAutoMutexExclusive ama(fStreamMutex);
 
         *fragmentStart = nullptr;
         *fragmentContext = nullptr;
diff --git a/tests/SkRemoteGlyphCacheTest.cpp b/tests/SkRemoteGlyphCacheTest.cpp
index 24169b4..2942f3b 100644
--- a/tests/SkRemoteGlyphCacheTest.cpp
+++ b/tests/SkRemoteGlyphCacheTest.cpp
@@ -31,14 +31,14 @@
 
     // Server implementation.
     SkDiscardableHandleId createHandle() override {
-        SkAutoMutexAcquire l(&fMutex);
+        SkAutoMutexExclusive l(fMutex);
 
         // Handles starts as locked.
         fLockedHandles.add(++fNextHandleId);
         return fNextHandleId;
     }
     bool lockHandle(SkDiscardableHandleId id) override {
-        SkAutoMutexAcquire l(&fMutex);
+        SkAutoMutexExclusive l(fMutex);
 
         if (id <= fLastDeletedHandleId) return false;
         fLockedHandles.add(id);
@@ -47,50 +47,50 @@
 
     // Client implementation.
     bool deleteHandle(SkDiscardableHandleId id) override {
-        SkAutoMutexAcquire l(&fMutex);
+        SkAutoMutexExclusive l(fMutex);
 
         return id <= fLastDeletedHandleId;
     }
 
     void notifyCacheMiss(SkStrikeClient::CacheMissType type) override {
-        SkAutoMutexAcquire l(&fMutex);
+        SkAutoMutexExclusive l(fMutex);
 
         fCacheMissCount[type]++;
     }
     bool isHandleDeleted(SkDiscardableHandleId id) override {
-        SkAutoMutexAcquire l(&fMutex);
+        SkAutoMutexExclusive l(fMutex);
 
         return id <= fLastDeletedHandleId;
     }
 
     void unlockAll() {
-        SkAutoMutexAcquire l(&fMutex);
+        SkAutoMutexExclusive l(fMutex);
 
         fLockedHandles.reset();
     }
     void unlockAndDeleteAll() {
-        SkAutoMutexAcquire l(&fMutex);
+        SkAutoMutexExclusive l(fMutex);
 
         fLockedHandles.reset();
         fLastDeletedHandleId = fNextHandleId;
     }
     const SkTHashSet<SkDiscardableHandleId>& lockedHandles() const {
-        SkAutoMutexAcquire l(&fMutex);
+        SkAutoMutexExclusive l(fMutex);
 
         return fLockedHandles;
     }
     SkDiscardableHandleId handleCount() {
-        SkAutoMutexAcquire l(&fMutex);
+        SkAutoMutexExclusive l(fMutex);
 
         return fNextHandleId;
     }
     int cacheMissCount(uint32_t type) {
-        SkAutoMutexAcquire l(&fMutex);
+        SkAutoMutexExclusive l(fMutex);
 
         return fCacheMissCount[type];
     }
     bool hasCacheMiss() const {
-        SkAutoMutexAcquire l(&fMutex);
+        SkAutoMutexExclusive l(fMutex);
 
         for (uint32_t i = 0; i <= SkStrikeClient::CacheMissType::kLast; ++i) {
             if (fCacheMissCount[i] > 0) return true;
diff --git a/tools/fonts/TestSVGTypeface.cpp b/tools/fonts/TestSVGTypeface.cpp
index 4069434..1582bb4 100644
--- a/tools/fonts/TestSVGTypeface.cpp
+++ b/tools/fonts/TestSVGTypeface.cpp
@@ -70,7 +70,7 @@
 
 template <typename Fn>
 void TestSVGTypeface::Glyph::withSVG(Fn&& fn) const {
-    SkAutoExclusive lock(fSvgMutex);
+    SkAutoMutexExclusive lock(fSvgMutex);
 
     if (!fParsedSvg) {
         fParsedSvg = true;
diff --git a/tools/trace/EventTracingPriv.cpp b/tools/trace/EventTracingPriv.cpp
index 43fc430..47a7f52 100644
--- a/tools/trace/EventTracingPriv.cpp
+++ b/tools/trace/EventTracingPriv.cpp
@@ -59,7 +59,7 @@
     // Chrome's implementation of this API does a two-phase lookup (once without a lock, then again
     // with a lock. But the tracing macros avoid calling these functions more than once per site,
     // so just do something simple (and easier to reason about):
-    SkAutoMutexAcquire lock(&fMutex);
+    SkAutoMutexExclusive lock(fMutex);
     for (int i = 0; i < fNumCategories; ++i) {
         if (0 == strcmp(name, fCategories[i].fName)) {
             return reinterpret_cast<uint8_t*>(&fCategories[i]);