1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/core/SkSharedMutex.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 11cb93a386Sopenharmony_ci#include "include/private/SkSemaphore.h" 12cb93a386Sopenharmony_ci 13cb93a386Sopenharmony_ci#include <cinttypes> 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#if !defined(__has_feature) 16cb93a386Sopenharmony_ci #define __has_feature(x) 0 17cb93a386Sopenharmony_ci#endif 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#if __has_feature(thread_sanitizer) 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci /* Report that a lock has been created at address "lock". */ 22cb93a386Sopenharmony_ci #define ANNOTATE_RWLOCK_CREATE(lock) \ 23cb93a386Sopenharmony_ci AnnotateRWLockCreate(__FILE__, __LINE__, lock) 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ci /* Report that the lock at address "lock" is about to be destroyed. */ 26cb93a386Sopenharmony_ci #define ANNOTATE_RWLOCK_DESTROY(lock) \ 27cb93a386Sopenharmony_ci AnnotateRWLockDestroy(__FILE__, __LINE__, lock) 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci /* Report that the lock at address "lock" has been acquired. 30cb93a386Sopenharmony_ci is_w=1 for writer lock, is_w=0 for reader lock. */ 31cb93a386Sopenharmony_ci #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \ 32cb93a386Sopenharmony_ci AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w) 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci /* Report that the lock at address "lock" is about to be released. */ 35cb93a386Sopenharmony_ci #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \ 36cb93a386Sopenharmony_ci AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w) 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci #if defined(DYNAMIC_ANNOTATIONS_WANT_ATTRIBUTE_WEAK) 39cb93a386Sopenharmony_ci #if defined(__GNUC__) 40cb93a386Sopenharmony_ci #define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK __attribute__((weak)) 41cb93a386Sopenharmony_ci #else 42cb93a386Sopenharmony_ci /* TODO(glider): for Windows support we may want to change this macro in order 43cb93a386Sopenharmony_ci to prepend __declspec(selectany) to the annotations' declarations. */ 44cb93a386Sopenharmony_ci #error weak annotations are not supported for your compiler 45cb93a386Sopenharmony_ci #endif 46cb93a386Sopenharmony_ci #else 47cb93a386Sopenharmony_ci #define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK 48cb93a386Sopenharmony_ci #endif 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ci extern "C" { 51cb93a386Sopenharmony_ci void AnnotateRWLockCreate( 52cb93a386Sopenharmony_ci const char *file, int line, 53cb93a386Sopenharmony_ci const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; 54cb93a386Sopenharmony_ci void AnnotateRWLockDestroy( 55cb93a386Sopenharmony_ci const char *file, int line, 56cb93a386Sopenharmony_ci const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; 57cb93a386Sopenharmony_ci void AnnotateRWLockAcquired( 58cb93a386Sopenharmony_ci const char *file, int line, 59cb93a386Sopenharmony_ci const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; 60cb93a386Sopenharmony_ci void AnnotateRWLockReleased( 61cb93a386Sopenharmony_ci const char *file, int line, 62cb93a386Sopenharmony_ci const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci#else 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci #define ANNOTATE_RWLOCK_CREATE(lock) 68cb93a386Sopenharmony_ci #define ANNOTATE_RWLOCK_DESTROY(lock) 69cb93a386Sopenharmony_ci #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) 70cb93a386Sopenharmony_ci #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci#endif 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci#ifdef SK_DEBUG 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci #include "include/private/SkTDArray.h" 77cb93a386Sopenharmony_ci #include "include/private/SkThreadID.h" 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci class SkSharedMutex::ThreadIDSet { 80cb93a386Sopenharmony_ci public: 81cb93a386Sopenharmony_ci // Returns true if threadID is in the set. 82cb93a386Sopenharmony_ci bool find(SkThreadID threadID) const { 83cb93a386Sopenharmony_ci for (auto& t : fThreadIDs) { 84cb93a386Sopenharmony_ci if (t == threadID) return true; 85cb93a386Sopenharmony_ci } 86cb93a386Sopenharmony_ci return false; 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci // Returns true if did not already exist. 90cb93a386Sopenharmony_ci bool tryAdd(SkThreadID threadID) { 91cb93a386Sopenharmony_ci for (auto& t : fThreadIDs) { 92cb93a386Sopenharmony_ci if (t == threadID) return false; 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci fThreadIDs.append(1, &threadID); 95cb93a386Sopenharmony_ci return true; 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci // Returns true if already exists in Set. 98cb93a386Sopenharmony_ci bool tryRemove(SkThreadID threadID) { 99cb93a386Sopenharmony_ci for (int i = 0; i < fThreadIDs.count(); ++i) { 100cb93a386Sopenharmony_ci if (fThreadIDs[i] == threadID) { 101cb93a386Sopenharmony_ci fThreadIDs.remove(i); 102cb93a386Sopenharmony_ci return true; 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci return false; 106cb93a386Sopenharmony_ci } 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci void swap(ThreadIDSet& other) { 109cb93a386Sopenharmony_ci fThreadIDs.swap(other.fThreadIDs); 110cb93a386Sopenharmony_ci } 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci int count() const { 113cb93a386Sopenharmony_ci return fThreadIDs.count(); 114cb93a386Sopenharmony_ci } 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci private: 117cb93a386Sopenharmony_ci SkTDArray<SkThreadID> fThreadIDs; 118cb93a386Sopenharmony_ci }; 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci SkSharedMutex::SkSharedMutex() 121cb93a386Sopenharmony_ci : fCurrentShared(new ThreadIDSet) 122cb93a386Sopenharmony_ci , fWaitingExclusive(new ThreadIDSet) 123cb93a386Sopenharmony_ci , fWaitingShared(new ThreadIDSet){ 124cb93a386Sopenharmony_ci ANNOTATE_RWLOCK_CREATE(this); 125cb93a386Sopenharmony_ci } 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ci SkSharedMutex::~SkSharedMutex() { ANNOTATE_RWLOCK_DESTROY(this); } 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci void SkSharedMutex::acquire() { 130cb93a386Sopenharmony_ci SkThreadID threadID(SkGetThreadID()); 131cb93a386Sopenharmony_ci int currentSharedCount; 132cb93a386Sopenharmony_ci int waitingExclusiveCount; 133cb93a386Sopenharmony_ci { 134cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMu); 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci SkASSERTF(!fCurrentShared->find(threadID), 137cb93a386Sopenharmony_ci "Thread %" PRIx64 " already has an shared lock\n", threadID); 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci if (!fWaitingExclusive->tryAdd(threadID)) { 140cb93a386Sopenharmony_ci SkDEBUGFAILF("Thread %" PRIx64 " already has an exclusive lock\n", threadID); 141cb93a386Sopenharmony_ci } 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci currentSharedCount = fCurrentShared->count(); 144cb93a386Sopenharmony_ci waitingExclusiveCount = fWaitingExclusive->count(); 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci if (currentSharedCount > 0 || waitingExclusiveCount > 1) { 148cb93a386Sopenharmony_ci fExclusiveQueue.wait(); 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci ANNOTATE_RWLOCK_ACQUIRED(this, 1); 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_ci // Implementation Detail: 155cb93a386Sopenharmony_ci // The shared threads need two separate queues to keep the threads that were added after the 156cb93a386Sopenharmony_ci // exclusive lock separate from the threads added before. 157cb93a386Sopenharmony_ci void SkSharedMutex::release() { 158cb93a386Sopenharmony_ci ANNOTATE_RWLOCK_RELEASED(this, 1); 159cb93a386Sopenharmony_ci SkThreadID threadID(SkGetThreadID()); 160cb93a386Sopenharmony_ci int sharedWaitingCount; 161cb93a386Sopenharmony_ci int exclusiveWaitingCount; 162cb93a386Sopenharmony_ci int sharedQueueSelect; 163cb93a386Sopenharmony_ci { 164cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMu); 165cb93a386Sopenharmony_ci SkASSERT(0 == fCurrentShared->count()); 166cb93a386Sopenharmony_ci if (!fWaitingExclusive->tryRemove(threadID)) { 167cb93a386Sopenharmony_ci SkDEBUGFAILF("Thread %" PRIx64 " did not have the lock held.\n", threadID); 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci exclusiveWaitingCount = fWaitingExclusive->count(); 170cb93a386Sopenharmony_ci sharedWaitingCount = fWaitingShared->count(); 171cb93a386Sopenharmony_ci fWaitingShared.swap(fCurrentShared); 172cb93a386Sopenharmony_ci sharedQueueSelect = fSharedQueueSelect; 173cb93a386Sopenharmony_ci if (sharedWaitingCount > 0) { 174cb93a386Sopenharmony_ci fSharedQueueSelect = 1 - fSharedQueueSelect; 175cb93a386Sopenharmony_ci } 176cb93a386Sopenharmony_ci } 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci if (sharedWaitingCount > 0) { 179cb93a386Sopenharmony_ci fSharedQueue[sharedQueueSelect].signal(sharedWaitingCount); 180cb93a386Sopenharmony_ci } else if (exclusiveWaitingCount > 0) { 181cb93a386Sopenharmony_ci fExclusiveQueue.signal(); 182cb93a386Sopenharmony_ci } 183cb93a386Sopenharmony_ci } 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_ci void SkSharedMutex::assertHeld() const { 186cb93a386Sopenharmony_ci SkThreadID threadID(SkGetThreadID()); 187cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMu); 188cb93a386Sopenharmony_ci SkASSERT(0 == fCurrentShared->count()); 189cb93a386Sopenharmony_ci SkASSERT(fWaitingExclusive->find(threadID)); 190cb93a386Sopenharmony_ci } 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_ci void SkSharedMutex::acquireShared() { 193cb93a386Sopenharmony_ci SkThreadID threadID(SkGetThreadID()); 194cb93a386Sopenharmony_ci int exclusiveWaitingCount; 195cb93a386Sopenharmony_ci int sharedQueueSelect; 196cb93a386Sopenharmony_ci { 197cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMu); 198cb93a386Sopenharmony_ci exclusiveWaitingCount = fWaitingExclusive->count(); 199cb93a386Sopenharmony_ci if (exclusiveWaitingCount > 0) { 200cb93a386Sopenharmony_ci if (!fWaitingShared->tryAdd(threadID)) { 201cb93a386Sopenharmony_ci SkDEBUGFAILF("Thread %" PRIx64 " was already waiting!\n", threadID); 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci } else { 204cb93a386Sopenharmony_ci if (!fCurrentShared->tryAdd(threadID)) { 205cb93a386Sopenharmony_ci SkDEBUGFAILF("Thread %" PRIx64 " already holds a shared lock!\n", threadID); 206cb93a386Sopenharmony_ci } 207cb93a386Sopenharmony_ci } 208cb93a386Sopenharmony_ci sharedQueueSelect = fSharedQueueSelect; 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci if (exclusiveWaitingCount > 0) { 212cb93a386Sopenharmony_ci fSharedQueue[sharedQueueSelect].wait(); 213cb93a386Sopenharmony_ci } 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_ci ANNOTATE_RWLOCK_ACQUIRED(this, 0); 216cb93a386Sopenharmony_ci } 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci void SkSharedMutex::releaseShared() { 219cb93a386Sopenharmony_ci ANNOTATE_RWLOCK_RELEASED(this, 0); 220cb93a386Sopenharmony_ci SkThreadID threadID(SkGetThreadID()); 221cb93a386Sopenharmony_ci 222cb93a386Sopenharmony_ci int currentSharedCount; 223cb93a386Sopenharmony_ci int waitingExclusiveCount; 224cb93a386Sopenharmony_ci { 225cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMu); 226cb93a386Sopenharmony_ci if (!fCurrentShared->tryRemove(threadID)) { 227cb93a386Sopenharmony_ci SkDEBUGFAILF("Thread %" PRIx64 " does not hold a shared lock.\n", threadID); 228cb93a386Sopenharmony_ci } 229cb93a386Sopenharmony_ci currentSharedCount = fCurrentShared->count(); 230cb93a386Sopenharmony_ci waitingExclusiveCount = fWaitingExclusive->count(); 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ci if (0 == currentSharedCount && waitingExclusiveCount > 0) { 234cb93a386Sopenharmony_ci fExclusiveQueue.signal(); 235cb93a386Sopenharmony_ci } 236cb93a386Sopenharmony_ci } 237cb93a386Sopenharmony_ci 238cb93a386Sopenharmony_ci void SkSharedMutex::assertHeldShared() const { 239cb93a386Sopenharmony_ci SkThreadID threadID(SkGetThreadID()); 240cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMu); 241cb93a386Sopenharmony_ci SkASSERT(fCurrentShared->find(threadID)); 242cb93a386Sopenharmony_ci } 243cb93a386Sopenharmony_ci 244cb93a386Sopenharmony_ci#else 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_ci // The fQueueCounts fields holds many counts in an int32_t in order to make managing them atomic. 247cb93a386Sopenharmony_ci // These three counts must be the same size, so each gets 10 bits. The 10 bits represent 248cb93a386Sopenharmony_ci // the log of the count which is 1024. 249cb93a386Sopenharmony_ci // 250cb93a386Sopenharmony_ci // The three counts held in fQueueCounts are: 251cb93a386Sopenharmony_ci // * Shared - the number of shared lock holders currently running. 252cb93a386Sopenharmony_ci // * WaitingExclusive - the number of threads waiting for an exclusive lock. 253cb93a386Sopenharmony_ci // * WaitingShared - the number of threads waiting to run while waiting for an exclusive thread 254cb93a386Sopenharmony_ci // to finish. 255cb93a386Sopenharmony_ci static const int kLogThreadCount = 10; 256cb93a386Sopenharmony_ci 257cb93a386Sopenharmony_ci enum { 258cb93a386Sopenharmony_ci kSharedOffset = (0 * kLogThreadCount), 259cb93a386Sopenharmony_ci kWaitingExlusiveOffset = (1 * kLogThreadCount), 260cb93a386Sopenharmony_ci kWaitingSharedOffset = (2 * kLogThreadCount), 261cb93a386Sopenharmony_ci kSharedMask = ((1 << kLogThreadCount) - 1) << kSharedOffset, 262cb93a386Sopenharmony_ci kWaitingExclusiveMask = ((1 << kLogThreadCount) - 1) << kWaitingExlusiveOffset, 263cb93a386Sopenharmony_ci kWaitingSharedMask = ((1 << kLogThreadCount) - 1) << kWaitingSharedOffset, 264cb93a386Sopenharmony_ci }; 265cb93a386Sopenharmony_ci 266cb93a386Sopenharmony_ci SkSharedMutex::SkSharedMutex() : fQueueCounts(0) { ANNOTATE_RWLOCK_CREATE(this); } 267cb93a386Sopenharmony_ci SkSharedMutex::~SkSharedMutex() { ANNOTATE_RWLOCK_DESTROY(this); } 268cb93a386Sopenharmony_ci void SkSharedMutex::acquire() { 269cb93a386Sopenharmony_ci // Increment the count of exclusive queue waiters. 270cb93a386Sopenharmony_ci int32_t oldQueueCounts = fQueueCounts.fetch_add(1 << kWaitingExlusiveOffset, 271cb93a386Sopenharmony_ci std::memory_order_acquire); 272cb93a386Sopenharmony_ci 273cb93a386Sopenharmony_ci // If there are no other exclusive waiters and no shared threads are running then run 274cb93a386Sopenharmony_ci // else wait. 275cb93a386Sopenharmony_ci if ((oldQueueCounts & kWaitingExclusiveMask) > 0 || (oldQueueCounts & kSharedMask) > 0) { 276cb93a386Sopenharmony_ci fExclusiveQueue.wait(); 277cb93a386Sopenharmony_ci } 278cb93a386Sopenharmony_ci ANNOTATE_RWLOCK_ACQUIRED(this, 1); 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci 281cb93a386Sopenharmony_ci void SkSharedMutex::release() { 282cb93a386Sopenharmony_ci ANNOTATE_RWLOCK_RELEASED(this, 1); 283cb93a386Sopenharmony_ci 284cb93a386Sopenharmony_ci int32_t oldQueueCounts = fQueueCounts.load(std::memory_order_relaxed); 285cb93a386Sopenharmony_ci int32_t waitingShared; 286cb93a386Sopenharmony_ci int32_t newQueueCounts; 287cb93a386Sopenharmony_ci do { 288cb93a386Sopenharmony_ci newQueueCounts = oldQueueCounts; 289cb93a386Sopenharmony_ci 290cb93a386Sopenharmony_ci // Decrement exclusive waiters. 291cb93a386Sopenharmony_ci newQueueCounts -= 1 << kWaitingExlusiveOffset; 292cb93a386Sopenharmony_ci 293cb93a386Sopenharmony_ci // The number of threads waiting to acquire a shared lock. 294cb93a386Sopenharmony_ci waitingShared = (oldQueueCounts & kWaitingSharedMask) >> kWaitingSharedOffset; 295cb93a386Sopenharmony_ci 296cb93a386Sopenharmony_ci // If there are any move the counts of all the shared waiters to actual shared. They are 297cb93a386Sopenharmony_ci // going to run next. 298cb93a386Sopenharmony_ci if (waitingShared > 0) { 299cb93a386Sopenharmony_ci 300cb93a386Sopenharmony_ci // Set waiting shared to zero. 301cb93a386Sopenharmony_ci newQueueCounts &= ~kWaitingSharedMask; 302cb93a386Sopenharmony_ci 303cb93a386Sopenharmony_ci // Because this is the exclusive release, then there are zero readers. So, the bits 304cb93a386Sopenharmony_ci // for shared locks should be zero. Since those bits are zero, we can just |= in the 305cb93a386Sopenharmony_ci // waitingShared count instead of clearing with an &= and then |= the count. 306cb93a386Sopenharmony_ci newQueueCounts |= waitingShared << kSharedOffset; 307cb93a386Sopenharmony_ci } 308cb93a386Sopenharmony_ci 309cb93a386Sopenharmony_ci } while (!fQueueCounts.compare_exchange_strong(oldQueueCounts, newQueueCounts, 310cb93a386Sopenharmony_ci std::memory_order_release, 311cb93a386Sopenharmony_ci std::memory_order_relaxed)); 312cb93a386Sopenharmony_ci 313cb93a386Sopenharmony_ci if (waitingShared > 0) { 314cb93a386Sopenharmony_ci // Run all the shared. 315cb93a386Sopenharmony_ci fSharedQueue.signal(waitingShared); 316cb93a386Sopenharmony_ci } else if ((newQueueCounts & kWaitingExclusiveMask) > 0) { 317cb93a386Sopenharmony_ci // Run a single exclusive waiter. 318cb93a386Sopenharmony_ci fExclusiveQueue.signal(); 319cb93a386Sopenharmony_ci } 320cb93a386Sopenharmony_ci } 321cb93a386Sopenharmony_ci 322cb93a386Sopenharmony_ci void SkSharedMutex::acquireShared() { 323cb93a386Sopenharmony_ci int32_t oldQueueCounts = fQueueCounts.load(std::memory_order_relaxed); 324cb93a386Sopenharmony_ci int32_t newQueueCounts; 325cb93a386Sopenharmony_ci do { 326cb93a386Sopenharmony_ci newQueueCounts = oldQueueCounts; 327cb93a386Sopenharmony_ci // If there are waiting exclusives then this shared lock waits else it runs. 328cb93a386Sopenharmony_ci if ((newQueueCounts & kWaitingExclusiveMask) > 0) { 329cb93a386Sopenharmony_ci newQueueCounts += 1 << kWaitingSharedOffset; 330cb93a386Sopenharmony_ci } else { 331cb93a386Sopenharmony_ci newQueueCounts += 1 << kSharedOffset; 332cb93a386Sopenharmony_ci } 333cb93a386Sopenharmony_ci } while (!fQueueCounts.compare_exchange_strong(oldQueueCounts, newQueueCounts, 334cb93a386Sopenharmony_ci std::memory_order_acquire, 335cb93a386Sopenharmony_ci std::memory_order_relaxed)); 336cb93a386Sopenharmony_ci 337cb93a386Sopenharmony_ci // If there are waiting exclusives, then this shared waits until after it runs. 338cb93a386Sopenharmony_ci if ((newQueueCounts & kWaitingExclusiveMask) > 0) { 339cb93a386Sopenharmony_ci fSharedQueue.wait(); 340cb93a386Sopenharmony_ci } 341cb93a386Sopenharmony_ci ANNOTATE_RWLOCK_ACQUIRED(this, 0); 342cb93a386Sopenharmony_ci 343cb93a386Sopenharmony_ci } 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_ci void SkSharedMutex::releaseShared() { 346cb93a386Sopenharmony_ci ANNOTATE_RWLOCK_RELEASED(this, 0); 347cb93a386Sopenharmony_ci 348cb93a386Sopenharmony_ci // Decrement the shared count. 349cb93a386Sopenharmony_ci int32_t oldQueueCounts = fQueueCounts.fetch_sub(1 << kSharedOffset, 350cb93a386Sopenharmony_ci std::memory_order_release); 351cb93a386Sopenharmony_ci 352cb93a386Sopenharmony_ci // If shared count is going to zero (because the old count == 1) and there are exclusive 353cb93a386Sopenharmony_ci // waiters, then run a single exclusive waiter. 354cb93a386Sopenharmony_ci if (((oldQueueCounts & kSharedMask) >> kSharedOffset) == 1 355cb93a386Sopenharmony_ci && (oldQueueCounts & kWaitingExclusiveMask) > 0) { 356cb93a386Sopenharmony_ci fExclusiveQueue.signal(); 357cb93a386Sopenharmony_ci } 358cb93a386Sopenharmony_ci } 359cb93a386Sopenharmony_ci 360cb93a386Sopenharmony_ci#endif 361