• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/base/platform/mutex.h"
6 
7 #include <errno.h>
8 
9 namespace v8 {
10 namespace base {
11 
12 #if V8_OS_POSIX
13 
InitializeNativeHandle(pthread_mutex_t * mutex)14 static V8_INLINE void InitializeNativeHandle(pthread_mutex_t* mutex) {
15   int result;
16 #if defined(DEBUG)
17   // Use an error checking mutex in debug mode.
18   pthread_mutexattr_t attr;
19   result = pthread_mutexattr_init(&attr);
20   DCHECK_EQ(0, result);
21   result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
22   DCHECK_EQ(0, result);
23   result = pthread_mutex_init(mutex, &attr);
24   DCHECK_EQ(0, result);
25   result = pthread_mutexattr_destroy(&attr);
26 #else
27   // Use a fast mutex (default attributes).
28   result = pthread_mutex_init(mutex, nullptr);
29 #endif  // defined(DEBUG)
30   DCHECK_EQ(0, result);
31   USE(result);
32 }
33 
34 
InitializeRecursiveNativeHandle(pthread_mutex_t * mutex)35 static V8_INLINE void InitializeRecursiveNativeHandle(pthread_mutex_t* mutex) {
36   pthread_mutexattr_t attr;
37   int result = pthread_mutexattr_init(&attr);
38   DCHECK_EQ(0, result);
39   result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
40   DCHECK_EQ(0, result);
41   result = pthread_mutex_init(mutex, &attr);
42   DCHECK_EQ(0, result);
43   result = pthread_mutexattr_destroy(&attr);
44   DCHECK_EQ(0, result);
45   USE(result);
46 }
47 
48 
DestroyNativeHandle(pthread_mutex_t * mutex)49 static V8_INLINE void DestroyNativeHandle(pthread_mutex_t* mutex) {
50   int result = pthread_mutex_destroy(mutex);
51   DCHECK_EQ(0, result);
52   USE(result);
53 }
54 
55 
LockNativeHandle(pthread_mutex_t * mutex)56 static V8_INLINE void LockNativeHandle(pthread_mutex_t* mutex) {
57   int result = pthread_mutex_lock(mutex);
58   DCHECK_EQ(0, result);
59   USE(result);
60 }
61 
62 
UnlockNativeHandle(pthread_mutex_t * mutex)63 static V8_INLINE void UnlockNativeHandle(pthread_mutex_t* mutex) {
64   int result = pthread_mutex_unlock(mutex);
65   DCHECK_EQ(0, result);
66   USE(result);
67 }
68 
69 
TryLockNativeHandle(pthread_mutex_t * mutex)70 static V8_INLINE bool TryLockNativeHandle(pthread_mutex_t* mutex) {
71   int result = pthread_mutex_trylock(mutex);
72   if (result == EBUSY) {
73     return false;
74   }
75   DCHECK_EQ(0, result);
76   return true;
77 }
78 
79 
Mutex()80 Mutex::Mutex() {
81   InitializeNativeHandle(&native_handle_);
82 #ifdef DEBUG
83   level_ = 0;
84 #endif
85 }
86 
87 
~Mutex()88 Mutex::~Mutex() {
89   DestroyNativeHandle(&native_handle_);
90   DCHECK_EQ(0, level_);
91 }
92 
93 
Lock()94 void Mutex::Lock() {
95   LockNativeHandle(&native_handle_);
96   AssertUnheldAndMark();
97 }
98 
99 
Unlock()100 void Mutex::Unlock() {
101   AssertHeldAndUnmark();
102   UnlockNativeHandle(&native_handle_);
103 }
104 
105 
TryLock()106 bool Mutex::TryLock() {
107   if (!TryLockNativeHandle(&native_handle_)) {
108     return false;
109   }
110   AssertUnheldAndMark();
111   return true;
112 }
113 
114 
RecursiveMutex()115 RecursiveMutex::RecursiveMutex() {
116   InitializeRecursiveNativeHandle(&native_handle_);
117 #ifdef DEBUG
118   level_ = 0;
119 #endif
120 }
121 
122 
~RecursiveMutex()123 RecursiveMutex::~RecursiveMutex() {
124   DestroyNativeHandle(&native_handle_);
125   DCHECK_EQ(0, level_);
126 }
127 
128 
Lock()129 void RecursiveMutex::Lock() {
130   LockNativeHandle(&native_handle_);
131 #ifdef DEBUG
132   DCHECK_LE(0, level_);
133   level_++;
134 #endif
135 }
136 
137 
Unlock()138 void RecursiveMutex::Unlock() {
139 #ifdef DEBUG
140   DCHECK_LT(0, level_);
141   level_--;
142 #endif
143   UnlockNativeHandle(&native_handle_);
144 }
145 
146 
TryLock()147 bool RecursiveMutex::TryLock() {
148   if (!TryLockNativeHandle(&native_handle_)) {
149     return false;
150   }
151 #ifdef DEBUG
152   DCHECK_LE(0, level_);
153   level_++;
154 #endif
155   return true;
156 }
157 
SharedMutex()158 SharedMutex::SharedMutex() { pthread_rwlock_init(&native_handle_, nullptr); }
159 
~SharedMutex()160 SharedMutex::~SharedMutex() {
161   int result = pthread_rwlock_destroy(&native_handle_);
162   DCHECK_EQ(0, result);
163   USE(result);
164 }
165 
LockShared()166 void SharedMutex::LockShared() {
167   int result = pthread_rwlock_rdlock(&native_handle_);
168   DCHECK_EQ(0, result);
169   USE(result);
170 }
171 
LockExclusive()172 void SharedMutex::LockExclusive() {
173   int result = pthread_rwlock_wrlock(&native_handle_);
174   DCHECK_EQ(0, result);
175   USE(result);
176 }
177 
UnlockShared()178 void SharedMutex::UnlockShared() {
179   int result = pthread_rwlock_unlock(&native_handle_);
180   DCHECK_EQ(0, result);
181   USE(result);
182 }
183 
UnlockExclusive()184 void SharedMutex::UnlockExclusive() {
185   // Same code as {UnlockShared} on POSIX.
186   UnlockShared();
187 }
188 
TryLockShared()189 bool SharedMutex::TryLockShared() {
190   return pthread_rwlock_tryrdlock(&native_handle_) == 0;
191 }
192 
TryLockExclusive()193 bool SharedMutex::TryLockExclusive() {
194   return pthread_rwlock_trywrlock(&native_handle_) == 0;
195 }
196 
197 #elif V8_OS_WIN
198 
199 Mutex::Mutex() : native_handle_(SRWLOCK_INIT) {
200 #ifdef DEBUG
201   level_ = 0;
202 #endif
203 }
204 
205 
206 Mutex::~Mutex() {
207   DCHECK_EQ(0, level_);
208 }
209 
210 
211 void Mutex::Lock() {
212   AcquireSRWLockExclusive(&native_handle_);
213   AssertUnheldAndMark();
214 }
215 
216 
217 void Mutex::Unlock() {
218   AssertHeldAndUnmark();
219   ReleaseSRWLockExclusive(&native_handle_);
220 }
221 
222 
223 bool Mutex::TryLock() {
224   if (!TryAcquireSRWLockExclusive(&native_handle_)) {
225     return false;
226   }
227   AssertUnheldAndMark();
228   return true;
229 }
230 
231 
232 RecursiveMutex::RecursiveMutex() {
233   InitializeCriticalSection(&native_handle_);
234 #ifdef DEBUG
235   level_ = 0;
236 #endif
237 }
238 
239 
240 RecursiveMutex::~RecursiveMutex() {
241   DeleteCriticalSection(&native_handle_);
242   DCHECK_EQ(0, level_);
243 }
244 
245 
246 void RecursiveMutex::Lock() {
247   EnterCriticalSection(&native_handle_);
248 #ifdef DEBUG
249   DCHECK_LE(0, level_);
250   level_++;
251 #endif
252 }
253 
254 
255 void RecursiveMutex::Unlock() {
256 #ifdef DEBUG
257   DCHECK_LT(0, level_);
258   level_--;
259 #endif
260   LeaveCriticalSection(&native_handle_);
261 }
262 
263 
264 bool RecursiveMutex::TryLock() {
265   if (!TryEnterCriticalSection(&native_handle_)) {
266     return false;
267   }
268 #ifdef DEBUG
269   DCHECK_LE(0, level_);
270   level_++;
271 #endif
272   return true;
273 }
274 
275 SharedMutex::SharedMutex() : native_handle_(SRWLOCK_INIT) {}
276 
277 SharedMutex::~SharedMutex() {}
278 
279 void SharedMutex::LockShared() { AcquireSRWLockShared(&native_handle_); }
280 
281 void SharedMutex::LockExclusive() { AcquireSRWLockExclusive(&native_handle_); }
282 
283 void SharedMutex::UnlockShared() { ReleaseSRWLockShared(&native_handle_); }
284 
285 void SharedMutex::UnlockExclusive() {
286   ReleaseSRWLockExclusive(&native_handle_);
287 }
288 
289 bool SharedMutex::TryLockShared() {
290   return TryAcquireSRWLockShared(&native_handle_);
291 }
292 
293 bool SharedMutex::TryLockExclusive() {
294   return TryAcquireSRWLockExclusive(&native_handle_);
295 }
296 
297 #elif V8_OS_STARBOARD
298 
299 Mutex::Mutex() { SbMutexCreate(&native_handle_); }
300 
301 Mutex::~Mutex() { SbMutexDestroy(&native_handle_); }
302 
303 void Mutex::Lock() { SbMutexAcquire(&native_handle_); }
304 
305 void Mutex::Unlock() { SbMutexRelease(&native_handle_); }
306 
307 RecursiveMutex::RecursiveMutex() {}
308 
309 RecursiveMutex::~RecursiveMutex() {}
310 
311 void RecursiveMutex::Lock() { native_handle_.Acquire(); }
312 
313 void RecursiveMutex::Unlock() { native_handle_.Release(); }
314 
315 bool RecursiveMutex::TryLock() { return native_handle_.AcquireTry(); }
316 
317 SharedMutex::SharedMutex() = default;
318 
319 SharedMutex::~SharedMutex() = default;
320 
321 void SharedMutex::LockShared() { native_handle_.AcquireReadLock(); }
322 
323 void SharedMutex::LockExclusive() { native_handle_.AcquireWriteLock(); }
324 
325 void SharedMutex::UnlockShared() { native_handle_.ReleaseReadLock(); }
326 
327 void SharedMutex::UnlockExclusive() { native_handle_.ReleaseWriteLock(); }
328 
329 bool SharedMutex::TryLockShared() { return false; }
330 
331 bool SharedMutex::TryLockExclusive() { return false; }
332 #endif  // V8_OS_STARBOARD
333 
334 }  // namespace base
335 }  // namespace v8
336