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, NULL);
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 #elif V8_OS_WIN
80
81 static V8_INLINE void InitializeNativeHandle(PCRITICAL_SECTION cs) {
82 InitializeCriticalSection(cs);
83 }
84
85
86 static V8_INLINE void InitializeRecursiveNativeHandle(PCRITICAL_SECTION cs) {
87 InitializeCriticalSection(cs);
88 }
89
90
91 static V8_INLINE void DestroyNativeHandle(PCRITICAL_SECTION cs) {
92 DeleteCriticalSection(cs);
93 }
94
95
96 static V8_INLINE void LockNativeHandle(PCRITICAL_SECTION cs) {
97 EnterCriticalSection(cs);
98 }
99
100
101 static V8_INLINE void UnlockNativeHandle(PCRITICAL_SECTION cs) {
102 LeaveCriticalSection(cs);
103 }
104
105
106 static V8_INLINE bool TryLockNativeHandle(PCRITICAL_SECTION cs) {
107 return TryEnterCriticalSection(cs);
108 }
109
110 #endif // V8_OS_POSIX
111
112
Mutex()113 Mutex::Mutex() {
114 InitializeNativeHandle(&native_handle_);
115 #ifdef DEBUG
116 level_ = 0;
117 #endif
118 }
119
120
~Mutex()121 Mutex::~Mutex() {
122 DestroyNativeHandle(&native_handle_);
123 DCHECK_EQ(0, level_);
124 }
125
126
Lock()127 void Mutex::Lock() {
128 LockNativeHandle(&native_handle_);
129 AssertUnheldAndMark();
130 }
131
132
Unlock()133 void Mutex::Unlock() {
134 AssertHeldAndUnmark();
135 UnlockNativeHandle(&native_handle_);
136 }
137
138
TryLock()139 bool Mutex::TryLock() {
140 if (!TryLockNativeHandle(&native_handle_)) {
141 return false;
142 }
143 AssertUnheldAndMark();
144 return true;
145 }
146
147
RecursiveMutex()148 RecursiveMutex::RecursiveMutex() {
149 InitializeRecursiveNativeHandle(&native_handle_);
150 #ifdef DEBUG
151 level_ = 0;
152 #endif
153 }
154
155
~RecursiveMutex()156 RecursiveMutex::~RecursiveMutex() {
157 DestroyNativeHandle(&native_handle_);
158 DCHECK_EQ(0, level_);
159 }
160
161
Lock()162 void RecursiveMutex::Lock() {
163 LockNativeHandle(&native_handle_);
164 #ifdef DEBUG
165 DCHECK_LE(0, level_);
166 level_++;
167 #endif
168 }
169
170
Unlock()171 void RecursiveMutex::Unlock() {
172 #ifdef DEBUG
173 DCHECK_LT(0, level_);
174 level_--;
175 #endif
176 UnlockNativeHandle(&native_handle_);
177 }
178
179
TryLock()180 bool RecursiveMutex::TryLock() {
181 if (!TryLockNativeHandle(&native_handle_)) {
182 return false;
183 }
184 #ifdef DEBUG
185 DCHECK_LE(0, level_);
186 level_++;
187 #endif
188 return true;
189 }
190
191 } // namespace base
192 } // namespace v8
193