| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkSharedMutex.h" | 8 #include "SkSharedMutex.h" |
| 9 | 9 |
| 10 #include "SkAtomics.h" | 10 #include "SkAtomics.h" |
| 11 #include "SkTypes.h" | 11 #include "SkTypes.h" |
| 12 #include "../private/SkSemaphore.h" | 12 #include "SkSemaphore.h" |
| 13 | 13 |
| 14 #if defined(THREAD_SANITIZER) | 14 #if defined(THREAD_SANITIZER) |
| 15 | 15 |
| 16 /* Report that a lock has been created at address "lock". */ | 16 /* Report that a lock has been created at address "lock". */ |
| 17 #define ANNOTATE_RWLOCK_CREATE(lock) \ | 17 #define ANNOTATE_RWLOCK_CREATE(lock) \ |
| 18 AnnotateRWLockCreate(__FILE__, __LINE__, lock) | 18 AnnotateRWLockCreate(__FILE__, __LINE__, lock) |
| 19 | 19 |
| 20 /* Report that the lock at address "lock" is about to be destroyed. */ | 20 /* Report that the lock at address "lock" is about to be destroyed. */ |
| 21 #define ANNOTATE_RWLOCK_DESTROY(lock) \ | 21 #define ANNOTATE_RWLOCK_DESTROY(lock) \ |
| 22 AnnotateRWLockDestroy(__FILE__, __LINE__, lock) | 22 AnnotateRWLockDestroy(__FILE__, __LINE__, lock) |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 | 61 |
| 62 #define ANNOTATE_RWLOCK_CREATE(lock) | 62 #define ANNOTATE_RWLOCK_CREATE(lock) |
| 63 #define ANNOTATE_RWLOCK_DESTROY(lock) | 63 #define ANNOTATE_RWLOCK_DESTROY(lock) |
| 64 #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) | 64 #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) |
| 65 #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) | 65 #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) |
| 66 | 66 |
| 67 #endif | 67 #endif |
| 68 | 68 |
| 69 #ifdef SK_DEBUG | 69 #ifdef SK_DEBUG |
| 70 | 70 |
| 71 #include "SkThreadID.h" |
| 71 #include "SkTDArray.h" | 72 #include "SkTDArray.h" |
| 72 #ifdef SK_BUILD_FOR_WIN | |
| 73 #include <windows.h> | |
| 74 static int64_t get_thread_id() { return GetCurrentThreadId(); } | |
| 75 #else | |
| 76 #include <pthread.h> | |
| 77 static int64_t get_thread_id() { return (int64_t)pthread_self(); } | |
| 78 #endif | |
| 79 | |
| 80 typedef int64_t ThreadID; | |
| 81 | 73 |
| 82 class SkSharedMutex::ThreadIDSet { | 74 class SkSharedMutex::ThreadIDSet { |
| 83 public: | 75 public: |
| 84 // Returns true if threadID is in the set. | 76 // Returns true if threadID is in the set. |
| 85 bool find(ThreadID threadID) const { | 77 bool find(SkThreadID threadID) const { |
| 86 for (auto& t : fThreadIDs) { | 78 for (auto& t : fThreadIDs) { |
| 87 if (t == threadID) return true; | 79 if (t == threadID) return true; |
| 88 } | 80 } |
| 89 return false; | 81 return false; |
| 90 } | 82 } |
| 91 | 83 |
| 92 // Returns true if did not already exist. | 84 // Returns true if did not already exist. |
| 93 bool tryAdd(ThreadID threadID) { | 85 bool tryAdd(SkThreadID threadID) { |
| 94 for (auto& t : fThreadIDs) { | 86 for (auto& t : fThreadIDs) { |
| 95 if (t == threadID) return false; | 87 if (t == threadID) return false; |
| 96 } | 88 } |
| 97 fThreadIDs.append(1, &threadID); | 89 fThreadIDs.append(1, &threadID); |
| 98 return true; | 90 return true; |
| 99 } | 91 } |
| 100 // Returns true if already exists in Set. | 92 // Returns true if already exists in Set. |
| 101 bool tryRemove(ThreadID threadID) { | 93 bool tryRemove(SkThreadID threadID) { |
| 102 for (int i = 0; i < fThreadIDs.count(); ++i) { | 94 for (int i = 0; i < fThreadIDs.count(); ++i) { |
| 103 if (fThreadIDs[i] == threadID) { | 95 if (fThreadIDs[i] == threadID) { |
| 104 fThreadIDs.remove(i); | 96 fThreadIDs.remove(i); |
| 105 return true; | 97 return true; |
| 106 } | 98 } |
| 107 } | 99 } |
| 108 return false; | 100 return false; |
| 109 } | 101 } |
| 110 | 102 |
| 111 void swap(ThreadIDSet& other) { | 103 void swap(ThreadIDSet& other) { |
| 112 fThreadIDs.swap(other.fThreadIDs); | 104 fThreadIDs.swap(other.fThreadIDs); |
| 113 } | 105 } |
| 114 | 106 |
| 115 int count() const { | 107 int count() const { |
| 116 return fThreadIDs.count(); | 108 return fThreadIDs.count(); |
| 117 } | 109 } |
| 118 | 110 |
| 119 private: | 111 private: |
| 120 SkTDArray<ThreadID> fThreadIDs; | 112 SkTDArray<SkThreadID> fThreadIDs; |
| 121 }; | 113 }; |
| 122 | 114 |
| 123 SkSharedMutex::SkSharedMutex() | 115 SkSharedMutex::SkSharedMutex() |
| 124 : fCurrentShared(new ThreadIDSet) | 116 : fCurrentShared(new ThreadIDSet) |
| 125 , fWaitingExclusive(new ThreadIDSet) | 117 , fWaitingExclusive(new ThreadIDSet) |
| 126 , fWaitingShared(new ThreadIDSet){ | 118 , fWaitingShared(new ThreadIDSet){ |
| 127 ANNOTATE_RWLOCK_CREATE(this); | 119 ANNOTATE_RWLOCK_CREATE(this); |
| 128 } | 120 } |
| 129 | 121 |
| 130 SkSharedMutex::~SkSharedMutex() { ANNOTATE_RWLOCK_DESTROY(this); } | 122 SkSharedMutex::~SkSharedMutex() { ANNOTATE_RWLOCK_DESTROY(this); } |
| 131 | 123 |
| 132 void SkSharedMutex::acquire() { | 124 void SkSharedMutex::acquire() { |
| 133 ThreadID threadID(get_thread_id()); | 125 SkThreadID threadID(SkGetThreadID()); |
| 134 int currentSharedCount; | 126 int currentSharedCount; |
| 135 int waitingExclusiveCount; | 127 int waitingExclusiveCount; |
| 136 { | 128 { |
| 137 SkAutoMutexAcquire l(&fMu); | 129 SkAutoMutexAcquire l(&fMu); |
| 138 | 130 |
| 139 if (!fWaitingExclusive->tryAdd(threadID)) { | 131 if (!fWaitingExclusive->tryAdd(threadID)) { |
| 140 SkDEBUGFAILF("Thread %lx already has an exclusive lock\n", threa
dID); | 132 SkDEBUGFAILF("Thread %lx already has an exclusive lock\n", threa
dID); |
| 141 } | 133 } |
| 142 | 134 |
| 143 currentSharedCount = fCurrentShared->count(); | 135 currentSharedCount = fCurrentShared->count(); |
| 144 waitingExclusiveCount = fWaitingExclusive->count(); | 136 waitingExclusiveCount = fWaitingExclusive->count(); |
| 145 } | 137 } |
| 146 | 138 |
| 147 if (currentSharedCount > 0 || waitingExclusiveCount > 1) { | 139 if (currentSharedCount > 0 || waitingExclusiveCount > 1) { |
| 148 fExclusiveQueue.wait(); | 140 fExclusiveQueue.wait(); |
| 149 } | 141 } |
| 150 | 142 |
| 151 ANNOTATE_RWLOCK_ACQUIRED(this, 1); | 143 ANNOTATE_RWLOCK_ACQUIRED(this, 1); |
| 152 } | 144 } |
| 153 | 145 |
| 154 // Implementation Detail: | 146 // Implementation Detail: |
| 155 // The shared threads need two seperate queues to keep the threads that were
added after the | 147 // The shared threads need two seperate queues to keep the threads that were
added after the |
| 156 // exclusive lock separate from the threads added before. | 148 // exclusive lock separate from the threads added before. |
| 157 void SkSharedMutex::release() { | 149 void SkSharedMutex::release() { |
| 158 ANNOTATE_RWLOCK_RELEASED(this, 1); | 150 ANNOTATE_RWLOCK_RELEASED(this, 1); |
| 159 ThreadID threadID(get_thread_id()); | 151 SkThreadID threadID(SkGetThreadID()); |
| 160 int sharedWaitingCount; | 152 int sharedWaitingCount; |
| 161 int exclusiveWaitingCount; | 153 int exclusiveWaitingCount; |
| 162 int sharedQueueSelect; | 154 int sharedQueueSelect; |
| 163 { | 155 { |
| 164 SkAutoMutexAcquire l(&fMu); | 156 SkAutoMutexAcquire l(&fMu); |
| 165 SkASSERT(0 == fCurrentShared->count()); | 157 SkASSERT(0 == fCurrentShared->count()); |
| 166 if (!fWaitingExclusive->tryRemove(threadID)) { | 158 if (!fWaitingExclusive->tryRemove(threadID)) { |
| 167 SkDEBUGFAILF("Thread %lx did not have the lock held.\n", threadI
D); | 159 SkDEBUGFAILF("Thread %lx did not have the lock held.\n", threadI
D); |
| 168 } | 160 } |
| 169 exclusiveWaitingCount = fWaitingExclusive->count(); | 161 exclusiveWaitingCount = fWaitingExclusive->count(); |
| 170 sharedWaitingCount = fWaitingShared->count(); | 162 sharedWaitingCount = fWaitingShared->count(); |
| 171 fWaitingShared.swap(fCurrentShared); | 163 fWaitingShared.swap(fCurrentShared); |
| 172 sharedQueueSelect = fSharedQueueSelect; | 164 sharedQueueSelect = fSharedQueueSelect; |
| 173 if (sharedWaitingCount > 0) { | 165 if (sharedWaitingCount > 0) { |
| 174 fSharedQueueSelect = 1 - fSharedQueueSelect; | 166 fSharedQueueSelect = 1 - fSharedQueueSelect; |
| 175 } | 167 } |
| 176 } | 168 } |
| 177 | 169 |
| 178 if (sharedWaitingCount > 0) { | 170 if (sharedWaitingCount > 0) { |
| 179 fSharedQueue[sharedQueueSelect].signal(sharedWaitingCount); | 171 fSharedQueue[sharedQueueSelect].signal(sharedWaitingCount); |
| 180 } else if (exclusiveWaitingCount > 0) { | 172 } else if (exclusiveWaitingCount > 0) { |
| 181 fExclusiveQueue.signal(); | 173 fExclusiveQueue.signal(); |
| 182 } | 174 } |
| 183 } | 175 } |
| 184 | 176 |
| 185 void SkSharedMutex::assertHeld() const { | 177 void SkSharedMutex::assertHeld() const { |
| 186 ThreadID threadID(get_thread_id()); | 178 SkThreadID threadID(SkGetThreadID()); |
| 187 SkAutoMutexAcquire l(&fMu); | 179 SkAutoMutexAcquire l(&fMu); |
| 188 SkASSERT(0 == fCurrentShared->count()); | 180 SkASSERT(0 == fCurrentShared->count()); |
| 189 SkASSERT(fWaitingExclusive->find(threadID)); | 181 SkASSERT(fWaitingExclusive->find(threadID)); |
| 190 } | 182 } |
| 191 | 183 |
| 192 void SkSharedMutex::acquireShared() { | 184 void SkSharedMutex::acquireShared() { |
| 193 ThreadID threadID(get_thread_id()); | 185 SkThreadID threadID(SkGetThreadID()); |
| 194 int exclusiveWaitingCount; | 186 int exclusiveWaitingCount; |
| 195 int sharedQueueSelect; | 187 int sharedQueueSelect; |
| 196 { | 188 { |
| 197 SkAutoMutexAcquire l(&fMu); | 189 SkAutoMutexAcquire l(&fMu); |
| 198 exclusiveWaitingCount = fWaitingExclusive->count(); | 190 exclusiveWaitingCount = fWaitingExclusive->count(); |
| 199 if (exclusiveWaitingCount > 0) { | 191 if (exclusiveWaitingCount > 0) { |
| 200 if (!fWaitingShared->tryAdd(threadID)) { | 192 if (!fWaitingShared->tryAdd(threadID)) { |
| 201 SkDEBUGFAILF("Thread %lx was already waiting!\n", threadID); | 193 SkDEBUGFAILF("Thread %lx was already waiting!\n", threadID); |
| 202 } | 194 } |
| 203 } else { | 195 } else { |
| 204 if (!fCurrentShared->tryAdd(threadID)) { | 196 if (!fCurrentShared->tryAdd(threadID)) { |
| 205 SkDEBUGFAILF("Thread %lx already holds a shared lock!\n", th
readID); | 197 SkDEBUGFAILF("Thread %lx already holds a shared lock!\n", th
readID); |
| 206 } | 198 } |
| 207 } | 199 } |
| 208 sharedQueueSelect = fSharedQueueSelect; | 200 sharedQueueSelect = fSharedQueueSelect; |
| 209 } | 201 } |
| 210 | 202 |
| 211 if (exclusiveWaitingCount > 0) { | 203 if (exclusiveWaitingCount > 0) { |
| 212 fSharedQueue[sharedQueueSelect].wait(); | 204 fSharedQueue[sharedQueueSelect].wait(); |
| 213 } | 205 } |
| 214 | 206 |
| 215 ANNOTATE_RWLOCK_ACQUIRED(this, 0); | 207 ANNOTATE_RWLOCK_ACQUIRED(this, 0); |
| 216 } | 208 } |
| 217 | 209 |
| 218 void SkSharedMutex::releaseShared() { | 210 void SkSharedMutex::releaseShared() { |
| 219 ANNOTATE_RWLOCK_RELEASED(this, 0); | 211 ANNOTATE_RWLOCK_RELEASED(this, 0); |
| 220 ThreadID threadID(get_thread_id()); | 212 SkThreadID threadID(SkGetThreadID()); |
| 221 | 213 |
| 222 int currentSharedCount; | 214 int currentSharedCount; |
| 223 int waitingExclusiveCount; | 215 int waitingExclusiveCount; |
| 224 { | 216 { |
| 225 SkAutoMutexAcquire l(&fMu); | 217 SkAutoMutexAcquire l(&fMu); |
| 226 if (!fCurrentShared->tryRemove(threadID)) { | 218 if (!fCurrentShared->tryRemove(threadID)) { |
| 227 SkDEBUGFAILF("Thread %lx does not hold a shared lock.\n", thread
ID); | 219 SkDEBUGFAILF("Thread %lx does not hold a shared lock.\n", thread
ID); |
| 228 } | 220 } |
| 229 currentSharedCount = fCurrentShared->count(); | 221 currentSharedCount = fCurrentShared->count(); |
| 230 waitingExclusiveCount = fWaitingExclusive->count(); | 222 waitingExclusiveCount = fWaitingExclusive->count(); |
| 231 } | 223 } |
| 232 | 224 |
| 233 if (0 == currentSharedCount && waitingExclusiveCount > 0) { | 225 if (0 == currentSharedCount && waitingExclusiveCount > 0) { |
| 234 fExclusiveQueue.signal(); | 226 fExclusiveQueue.signal(); |
| 235 } | 227 } |
| 236 } | 228 } |
| 237 | 229 |
| 238 void SkSharedMutex::assertHeldShared() const { | 230 void SkSharedMutex::assertHeldShared() const { |
| 239 ThreadID threadID(get_thread_id()); | 231 SkThreadID threadID(SkGetThreadID()); |
| 240 SkAutoMutexAcquire l(&fMu); | 232 SkAutoMutexAcquire l(&fMu); |
| 241 SkASSERT(fCurrentShared->find(threadID)); | 233 SkASSERT(fCurrentShared->find(threadID)); |
| 242 } | 234 } |
| 243 | 235 |
| 244 #else | 236 #else |
| 245 | 237 |
| 246 // The fQueueCounts fields holds many counts in an int32_t in order to make
managing them atomic. | 238 // The fQueueCounts fields holds many counts in an int32_t in order to make
managing them atomic. |
| 247 // These three counts must be the same size, so each gets 10 bits. The 10 bi
ts represent | 239 // These three counts must be the same size, so each gets 10 bits. The 10 bi
ts represent |
| 248 // the log of the count which is 1024. | 240 // the log of the count which is 1024. |
| 249 // | 241 // |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 | 341 |
| 350 // If shared count is going to zero (because the old count == 1) and the
re are exclusive | 342 // If shared count is going to zero (because the old count == 1) and the
re are exclusive |
| 351 // waiters, then run a single exclusive waiter. | 343 // waiters, then run a single exclusive waiter. |
| 352 if (((oldQueueCounts & kSharedMask) >> kSharedOffset) == 1 | 344 if (((oldQueueCounts & kSharedMask) >> kSharedOffset) == 1 |
| 353 && (oldQueueCounts & kWaitingExclusiveMask) > 0) { | 345 && (oldQueueCounts & kWaitingExclusiveMask) > 0) { |
| 354 fExclusiveQueue.signal(); | 346 fExclusiveQueue.signal(); |
| 355 } | 347 } |
| 356 } | 348 } |
| 357 | 349 |
| 358 #endif | 350 #endif |
| OLD | NEW |