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
158 #elif V8_OS_WIN
159
160 Mutex::Mutex() : native_handle_(SRWLOCK_INIT) {
161 #ifdef DEBUG
162 level_ = 0;
163 #endif
164 }
165
166
167 Mutex::~Mutex() {
168 DCHECK_EQ(0, level_);
169 }
170
171
172 void Mutex::Lock() {
173 AcquireSRWLockExclusive(&native_handle_);
174 AssertUnheldAndMark();
175 }
176
177
178 void Mutex::Unlock() {
179 AssertHeldAndUnmark();
180 ReleaseSRWLockExclusive(&native_handle_);
181 }
182
183
184 bool Mutex::TryLock() {
185 if (!TryAcquireSRWLockExclusive(&native_handle_)) {
186 return false;
187 }
188 AssertUnheldAndMark();
189 return true;
190 }
191
192
193 RecursiveMutex::RecursiveMutex() {
194 InitializeCriticalSection(&native_handle_);
195 #ifdef DEBUG
196 level_ = 0;
197 #endif
198 }
199
200
201 RecursiveMutex::~RecursiveMutex() {
202 DeleteCriticalSection(&native_handle_);
203 DCHECK_EQ(0, level_);
204 }
205
206
207 void RecursiveMutex::Lock() {
208 EnterCriticalSection(&native_handle_);
209 #ifdef DEBUG
210 DCHECK_LE(0, level_);
211 level_++;
212 #endif
213 }
214
215
216 void RecursiveMutex::Unlock() {
217 #ifdef DEBUG
218 DCHECK_LT(0, level_);
219 level_--;
220 #endif
221 LeaveCriticalSection(&native_handle_);
222 }
223
224
225 bool RecursiveMutex::TryLock() {
226 if (!TryEnterCriticalSection(&native_handle_)) {
227 return false;
228 }
229 #ifdef DEBUG
230 DCHECK_LE(0, level_);
231 level_++;
232 #endif
233 return true;
234 }
235
236 #endif // V8_OS_POSIX
237
238 } // namespace base
239 } // namespace v8
240