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 |