1c782b2a046763dc427fa47d4e33afca59c994d60herb/* 2c782b2a046763dc427fa47d4e33afca59c994d60herb * Copyright 2015 Google Inc. 3c782b2a046763dc427fa47d4e33afca59c994d60herb * 4c782b2a046763dc427fa47d4e33afca59c994d60herb * Use of this source code is governed by a BSD-style license that can be 5c782b2a046763dc427fa47d4e33afca59c994d60herb * found in the LICENSE file. 6c782b2a046763dc427fa47d4e33afca59c994d60herb */ 7c782b2a046763dc427fa47d4e33afca59c994d60herb 8c782b2a046763dc427fa47d4e33afca59c994d60herb#include "SkSharedMutex.h" 9c782b2a046763dc427fa47d4e33afca59c994d60herb 10b906daf112416c1698a79cf51aa70fe11aa19d0aherb#include "SkAtomics.h" 11c782b2a046763dc427fa47d4e33afca59c994d60herb#include "SkTypes.h" 12e4c17356b6c819df8effb29dfb4bb903520b8c2bherb#include "SkSemaphore.h" 13c782b2a046763dc427fa47d4e33afca59c994d60herb 143b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein#if !defined(__has_feature) 153b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #define __has_feature(x) 0 163b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein#endif 173b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein 183b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein#if __has_feature(thread_sanitizer) 193b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein 203b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein /* Report that a lock has been created at address "lock". */ 213b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #define ANNOTATE_RWLOCK_CREATE(lock) \ 223b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein AnnotateRWLockCreate(__FILE__, __LINE__, lock) 233b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein 243b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein /* Report that the lock at address "lock" is about to be destroyed. */ 253b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #define ANNOTATE_RWLOCK_DESTROY(lock) \ 263b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein AnnotateRWLockDestroy(__FILE__, __LINE__, lock) 273b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein 283b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein /* Report that the lock at address "lock" has been acquired. 293b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein is_w=1 for writer lock, is_w=0 for reader lock. */ 303b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \ 313b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w) 323b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein 333b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein /* Report that the lock at address "lock" is about to be released. */ 343b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \ 353b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w) 363b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein 373b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #if defined(DYNAMIC_ANNOTATIONS_WANT_ATTRIBUTE_WEAK) 383b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #if defined(__GNUC__) 393b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK __attribute__((weak)) 403b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #else 413b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein /* TODO(glider): for Windows support we may want to change this macro in order 423b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein to prepend __declspec(selectany) to the annotations' declarations. */ 433b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #error weak annotations are not supported for your compiler 443b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #endif 453b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #else 463b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK 473b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #endif 483b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein 493b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein extern "C" { 503b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein void AnnotateRWLockCreate( 513b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein const char *file, int line, 523b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; 533b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein void AnnotateRWLockDestroy( 543b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein const char *file, int line, 553b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; 563b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein void AnnotateRWLockAcquired( 573b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein const char *file, int line, 583b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; 593b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein void AnnotateRWLockReleased( 603b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein const char *file, int line, 613b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; 623b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein } 633b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein 643b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein#else 653b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein 663b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #define ANNOTATE_RWLOCK_CREATE(lock) 673b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #define ANNOTATE_RWLOCK_DESTROY(lock) 683b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) 693b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) 703b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein 713b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein#endif 723b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein 73966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb#ifdef SK_DEBUG 74966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 75e4c17356b6c819df8effb29dfb4bb903520b8c2bherb #include "SkThreadID.h" 76966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb #include "SkTDArray.h" 77966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 78966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb class SkSharedMutex::ThreadIDSet { 79966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb public: 80966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // Returns true if threadID is in the set. 81e4c17356b6c819df8effb29dfb4bb903520b8c2bherb bool find(SkThreadID threadID) const { 82966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb for (auto& t : fThreadIDs) { 83966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (t == threadID) return true; 84966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 85966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb return false; 86966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 87966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 88966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // Returns true if did not already exist. 89e4c17356b6c819df8effb29dfb4bb903520b8c2bherb bool tryAdd(SkThreadID threadID) { 90966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb for (auto& t : fThreadIDs) { 91966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (t == threadID) return false; 92966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 93966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fThreadIDs.append(1, &threadID); 94966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb return true; 95966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 96966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // Returns true if already exists in Set. 97e4c17356b6c819df8effb29dfb4bb903520b8c2bherb bool tryRemove(SkThreadID threadID) { 98966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb for (int i = 0; i < fThreadIDs.count(); ++i) { 99966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (fThreadIDs[i] == threadID) { 100966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fThreadIDs.remove(i); 101966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb return true; 102966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 103966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 104966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb return false; 105966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 106966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 107966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb void swap(ThreadIDSet& other) { 108966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fThreadIDs.swap(other.fThreadIDs); 109966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 110966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 111966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int count() const { 112966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb return fThreadIDs.count(); 113966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 114966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 115966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb private: 116e4c17356b6c819df8effb29dfb4bb903520b8c2bherb SkTDArray<SkThreadID> fThreadIDs; 117966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb }; 118966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 119966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkSharedMutex::SkSharedMutex() 120966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb : fCurrentShared(new ThreadIDSet) 121966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb , fWaitingExclusive(new ThreadIDSet) 122966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb , fWaitingShared(new ThreadIDSet){ 123966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb ANNOTATE_RWLOCK_CREATE(this); 124c782b2a046763dc427fa47d4e33afca59c994d60herb } 125c782b2a046763dc427fa47d4e33afca59c994d60herb 126966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkSharedMutex::~SkSharedMutex() { ANNOTATE_RWLOCK_DESTROY(this); } 127dec1afcf34dfb91f3bf0552feffc46b8865fcb36herb 128966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb void SkSharedMutex::acquire() { 129e4c17356b6c819df8effb29dfb4bb903520b8c2bherb SkThreadID threadID(SkGetThreadID()); 130966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int currentSharedCount; 131966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int waitingExclusiveCount; 132966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb { 133966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkAutoMutexAcquire l(&fMu); 134c782b2a046763dc427fa47d4e33afca59c994d60herb 135966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (!fWaitingExclusive->tryAdd(threadID)) { 136966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkDEBUGFAILF("Thread %lx already has an exclusive lock\n", threadID); 137966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 138c782b2a046763dc427fa47d4e33afca59c994d60herb 139966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb currentSharedCount = fCurrentShared->count(); 140966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb waitingExclusiveCount = fWaitingExclusive->count(); 141966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 142c782b2a046763dc427fa47d4e33afca59c994d60herb 143966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (currentSharedCount > 0 || waitingExclusiveCount > 1) { 144966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fExclusiveQueue.wait(); 145966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 146c782b2a046763dc427fa47d4e33afca59c994d60herb 147966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb ANNOTATE_RWLOCK_ACQUIRED(this, 1); 148966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 149c782b2a046763dc427fa47d4e33afca59c994d60herb 150966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // Implementation Detail: 151966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // The shared threads need two seperate queues to keep the threads that were added after the 152966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // exclusive lock separate from the threads added before. 153966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb void SkSharedMutex::release() { 154966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb ANNOTATE_RWLOCK_RELEASED(this, 1); 155e4c17356b6c819df8effb29dfb4bb903520b8c2bherb SkThreadID threadID(SkGetThreadID()); 156966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int sharedWaitingCount; 157966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int exclusiveWaitingCount; 158966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int sharedQueueSelect; 159966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb { 160966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkAutoMutexAcquire l(&fMu); 161966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkASSERT(0 == fCurrentShared->count()); 162966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (!fWaitingExclusive->tryRemove(threadID)) { 163966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkDEBUGFAILF("Thread %lx did not have the lock held.\n", threadID); 164966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 165966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb exclusiveWaitingCount = fWaitingExclusive->count(); 166966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb sharedWaitingCount = fWaitingShared->count(); 167966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fWaitingShared.swap(fCurrentShared); 168966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb sharedQueueSelect = fSharedQueueSelect; 169966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (sharedWaitingCount > 0) { 170966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fSharedQueueSelect = 1 - fSharedQueueSelect; 171966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 172c782b2a046763dc427fa47d4e33afca59c994d60herb } 173c782b2a046763dc427fa47d4e33afca59c994d60herb 174966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (sharedWaitingCount > 0) { 175966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fSharedQueue[sharedQueueSelect].signal(sharedWaitingCount); 176966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } else if (exclusiveWaitingCount > 0) { 177966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fExclusiveQueue.signal(); 178966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 179966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 180c782b2a046763dc427fa47d4e33afca59c994d60herb 181966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb void SkSharedMutex::assertHeld() const { 182e4c17356b6c819df8effb29dfb4bb903520b8c2bherb SkThreadID threadID(SkGetThreadID()); 183966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkAutoMutexAcquire l(&fMu); 184966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkASSERT(0 == fCurrentShared->count()); 185966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkASSERT(fWaitingExclusive->find(threadID)); 186c782b2a046763dc427fa47d4e33afca59c994d60herb } 187c782b2a046763dc427fa47d4e33afca59c994d60herb 188966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb void SkSharedMutex::acquireShared() { 189e4c17356b6c819df8effb29dfb4bb903520b8c2bherb SkThreadID threadID(SkGetThreadID()); 190966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int exclusiveWaitingCount; 191966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int sharedQueueSelect; 192966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb { 193966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkAutoMutexAcquire l(&fMu); 194966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb exclusiveWaitingCount = fWaitingExclusive->count(); 195966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (exclusiveWaitingCount > 0) { 196966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (!fWaitingShared->tryAdd(threadID)) { 197966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkDEBUGFAILF("Thread %lx was already waiting!\n", threadID); 198966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 199966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } else { 200966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (!fCurrentShared->tryAdd(threadID)) { 201966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkDEBUGFAILF("Thread %lx already holds a shared lock!\n", threadID); 202966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 203966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 204966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb sharedQueueSelect = fSharedQueueSelect; 205966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 206ab42ec79d5dbf38b81394c55670b495cdf78b243herb 207966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (exclusiveWaitingCount > 0) { 208966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fSharedQueue[sharedQueueSelect].wait(); 209c782b2a046763dc427fa47d4e33afca59c994d60herb } 210c782b2a046763dc427fa47d4e33afca59c994d60herb 211966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb ANNOTATE_RWLOCK_ACQUIRED(this, 0); 212966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 213966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 214966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb void SkSharedMutex::releaseShared() { 215966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb ANNOTATE_RWLOCK_RELEASED(this, 0); 216e4c17356b6c819df8effb29dfb4bb903520b8c2bherb SkThreadID threadID(SkGetThreadID()); 217966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 218966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int currentSharedCount; 219966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int waitingExclusiveCount; 220966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb { 221966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkAutoMutexAcquire l(&fMu); 222966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (!fCurrentShared->tryRemove(threadID)) { 223966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkDEBUGFAILF("Thread %lx does not hold a shared lock.\n", threadID); 224966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 225966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb currentSharedCount = fCurrentShared->count(); 226966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb waitingExclusiveCount = fWaitingExclusive->count(); 227966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 228966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 229966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (0 == currentSharedCount && waitingExclusiveCount > 0) { 230966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fExclusiveQueue.signal(); 231966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 232c782b2a046763dc427fa47d4e33afca59c994d60herb } 233c782b2a046763dc427fa47d4e33afca59c994d60herb 234966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb void SkSharedMutex::assertHeldShared() const { 235e4c17356b6c819df8effb29dfb4bb903520b8c2bherb SkThreadID threadID(SkGetThreadID()); 236966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkAutoMutexAcquire l(&fMu); 237966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkASSERT(fCurrentShared->find(threadID)); 238966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 239dec1afcf34dfb91f3bf0552feffc46b8865fcb36herb 240966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb#else 241c782b2a046763dc427fa47d4e33afca59c994d60herb 242966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // The fQueueCounts fields holds many counts in an int32_t in order to make managing them atomic. 243966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // These three counts must be the same size, so each gets 10 bits. The 10 bits represent 244966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // the log of the count which is 1024. 245966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // 246966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // The three counts held in fQueueCounts are: 247966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // * Shared - the number of shared lock holders currently running. 248966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // * WaitingExclusive - the number of threads waiting for an exclusive lock. 249966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // * WaitingShared - the number of threads waiting to run while waiting for an exclusive thread 250966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // to finish. 251966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb static const int kLogThreadCount = 10; 252966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 253966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb enum { 254966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb kSharedOffset = (0 * kLogThreadCount), 255966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb kWaitingExlusiveOffset = (1 * kLogThreadCount), 256966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb kWaitingSharedOffset = (2 * kLogThreadCount), 257966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb kSharedMask = ((1 << kLogThreadCount) - 1) << kSharedOffset, 258966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb kWaitingExclusiveMask = ((1 << kLogThreadCount) - 1) << kWaitingExlusiveOffset, 259966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb kWaitingSharedMask = ((1 << kLogThreadCount) - 1) << kWaitingSharedOffset, 260966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb }; 261966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 262966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkSharedMutex::SkSharedMutex() : fQueueCounts(0) { ANNOTATE_RWLOCK_CREATE(this); } 263966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb SkSharedMutex::~SkSharedMutex() { ANNOTATE_RWLOCK_DESTROY(this); } 264966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb void SkSharedMutex::acquire() { 265966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // Increment the count of exclusive queue waiters. 266966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int32_t oldQueueCounts = fQueueCounts.fetch_add(1 << kWaitingExlusiveOffset, 267966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb sk_memory_order_acquire); 268966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 269966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // If there are no other exclusive waiters and no shared threads are running then run 270966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // else wait. 271966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if ((oldQueueCounts & kWaitingExclusiveMask) > 0 || (oldQueueCounts & kSharedMask) > 0) { 272966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fExclusiveQueue.wait(); 273966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 274966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb ANNOTATE_RWLOCK_ACQUIRED(this, 1); 275c782b2a046763dc427fa47d4e33afca59c994d60herb } 276ab42ec79d5dbf38b81394c55670b495cdf78b243herb 277966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb void SkSharedMutex::release() { 278966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb ANNOTATE_RWLOCK_RELEASED(this, 1); 279966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 280966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int32_t oldQueueCounts = fQueueCounts.load(sk_memory_order_relaxed); 281966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int32_t waitingShared; 282966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int32_t newQueueCounts; 283966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb do { 284966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb newQueueCounts = oldQueueCounts; 285966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 286966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // Decrement exclusive waiters. 287966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb newQueueCounts -= 1 << kWaitingExlusiveOffset; 288966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 289966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // The number of threads waiting to acquire a shared lock. 290966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb waitingShared = (oldQueueCounts & kWaitingSharedMask) >> kWaitingSharedOffset; 291966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 292966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // If there are any move the counts of all the shared waiters to actual shared. They are 293966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // going to run next. 294966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (waitingShared > 0) { 295966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 296966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // Set waiting shared to zero. 297966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb newQueueCounts &= ~kWaitingSharedMask; 298966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 299966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // Because this is the exclusive release, then there are zero readers. So, the bits 300966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // for shared locks should be zero. Since those bits are zero, we can just |= in the 301966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // waitingShared count instead of clearing with an &= and then |= the count. 302966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb newQueueCounts |= waitingShared << kSharedOffset; 303966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 304966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 305966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } while (!fQueueCounts.compare_exchange(&oldQueueCounts, newQueueCounts, 306966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb sk_memory_order_release, sk_memory_order_relaxed)); 307966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 308966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (waitingShared > 0) { 309966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // Run all the shared. 310966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fSharedQueue.signal(waitingShared); 311966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } else if ((newQueueCounts & kWaitingExclusiveMask) > 0) { 312966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // Run a single exclusive waiter. 313966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fExclusiveQueue.signal(); 314966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 315966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 316966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 317966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb void SkSharedMutex::acquireShared() { 318966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int32_t oldQueueCounts = fQueueCounts.load(sk_memory_order_relaxed); 319966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int32_t newQueueCounts; 320966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb do { 321966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb newQueueCounts = oldQueueCounts; 322966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // If there are waiting exclusives then this shared lock waits else it runs. 323966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if ((newQueueCounts & kWaitingExclusiveMask) > 0) { 324966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb newQueueCounts += 1 << kWaitingSharedOffset; 325966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } else { 326966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb newQueueCounts += 1 << kSharedOffset; 327966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 328966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } while (!fQueueCounts.compare_exchange(&oldQueueCounts, newQueueCounts, 329966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb sk_memory_order_acquire, sk_memory_order_relaxed)); 330966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 331966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // If there are waiting exclusives, then this shared waits until after it runs. 332966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if ((newQueueCounts & kWaitingExclusiveMask) > 0) { 333966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fSharedQueue.wait(); 334966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 335966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb ANNOTATE_RWLOCK_ACQUIRED(this, 0); 336966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 337966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 338966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 339966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb void SkSharedMutex::releaseShared() { 340966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb ANNOTATE_RWLOCK_RELEASED(this, 0); 341966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 342966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // Decrement the shared count. 343966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb int32_t oldQueueCounts = fQueueCounts.fetch_sub(1 << kSharedOffset, 344966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb sk_memory_order_release); 345966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb 346966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // If shared count is going to zero (because the old count == 1) and there are exclusive 347966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb // waiters, then run a single exclusive waiter. 348966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb if (((oldQueueCounts & kSharedMask) >> kSharedOffset) == 1 349966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb && (oldQueueCounts & kWaitingExclusiveMask) > 0) { 350966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb fExclusiveQueue.signal(); 351966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 352966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb } 353ab42ec79d5dbf38b81394c55670b495cdf78b243herb 354ab42ec79d5dbf38b81394c55670b495cdf78b243herb#endif 355