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 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 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 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 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 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 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 80 Mutex::Mutex() { 81 InitializeNativeHandle(&native_handle_); 82 #ifdef DEBUG 83 level_ = 0; 84 #endif 85 } 86 87 88 Mutex::~Mutex() { 89 DestroyNativeHandle(&native_handle_); 90 DCHECK_EQ(0, level_); 91 } 92 93 94 void Mutex::Lock() { 95 LockNativeHandle(&native_handle_); 96 AssertUnheldAndMark(); 97 } 98 99 100 void Mutex::Unlock() { 101 AssertHeldAndUnmark(); 102 UnlockNativeHandle(&native_handle_); 103 } 104 105 106 bool Mutex::TryLock() { 107 if (!TryLockNativeHandle(&native_handle_)) { 108 return false; 109 } 110 AssertUnheldAndMark(); 111 return true; 112 } 113 114 115 RecursiveMutex::RecursiveMutex() { 116 InitializeRecursiveNativeHandle(&native_handle_); 117 #ifdef DEBUG 118 level_ = 0; 119 #endif 120 } 121 122 123 RecursiveMutex::~RecursiveMutex() { 124 DestroyNativeHandle(&native_handle_); 125 DCHECK_EQ(0, level_); 126 } 127 128 129 void RecursiveMutex::Lock() { 130 LockNativeHandle(&native_handle_); 131 #ifdef DEBUG 132 DCHECK_LE(0, level_); 133 level_++; 134 #endif 135 } 136 137 138 void RecursiveMutex::Unlock() { 139 #ifdef DEBUG 140 DCHECK_LT(0, level_); 141 level_--; 142 #endif 143 UnlockNativeHandle(&native_handle_); 144 } 145 146 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