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