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/platform/mutex.h" 6 7 #include <errno.h> 8 9 namespace v8 { 10 namespace internal { 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 ASSERT_EQ(0, result); 21 result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); 22 ASSERT_EQ(0, result); 23 result = pthread_mutex_init(mutex, &attr); 24 ASSERT_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 ASSERT_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 ASSERT_EQ(0, result); 39 result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 40 ASSERT_EQ(0, result); 41 result = pthread_mutex_init(mutex, &attr); 42 ASSERT_EQ(0, result); 43 result = pthread_mutexattr_destroy(&attr); 44 ASSERT_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 ASSERT_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 ASSERT_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 ASSERT_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 ASSERT_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 113 Mutex::Mutex() { 114 InitializeNativeHandle(&native_handle_); 115 #ifdef DEBUG 116 level_ = 0; 117 #endif 118 } 119 120 121 Mutex::~Mutex() { 122 DestroyNativeHandle(&native_handle_); 123 ASSERT_EQ(0, level_); 124 } 125 126 127 void Mutex::Lock() { 128 LockNativeHandle(&native_handle_); 129 AssertUnheldAndMark(); 130 } 131 132 133 void Mutex::Unlock() { 134 AssertHeldAndUnmark(); 135 UnlockNativeHandle(&native_handle_); 136 } 137 138 139 bool Mutex::TryLock() { 140 if (!TryLockNativeHandle(&native_handle_)) { 141 return false; 142 } 143 AssertUnheldAndMark(); 144 return true; 145 } 146 147 148 RecursiveMutex::RecursiveMutex() { 149 InitializeRecursiveNativeHandle(&native_handle_); 150 #ifdef DEBUG 151 level_ = 0; 152 #endif 153 } 154 155 156 RecursiveMutex::~RecursiveMutex() { 157 DestroyNativeHandle(&native_handle_); 158 ASSERT_EQ(0, level_); 159 } 160 161 162 void RecursiveMutex::Lock() { 163 LockNativeHandle(&native_handle_); 164 #ifdef DEBUG 165 ASSERT_LE(0, level_); 166 level_++; 167 #endif 168 } 169 170 171 void RecursiveMutex::Unlock() { 172 #ifdef DEBUG 173 ASSERT_LT(0, level_); 174 level_--; 175 #endif 176 UnlockNativeHandle(&native_handle_); 177 } 178 179 180 bool RecursiveMutex::TryLock() { 181 if (!TryLockNativeHandle(&native_handle_)) { 182 return false; 183 } 184 #ifdef DEBUG 185 ASSERT_LE(0, level_); 186 level_++; 187 #endif 188 return true; 189 } 190 191 } } // namespace v8::internal 192