1 // Copyright 2013 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include "platform/mutex.h" 29 30 #include <cerrno> 31 32 namespace v8 { 33 namespace internal { 34 35 #if V8_OS_POSIX 36 37 static V8_INLINE void InitializeNativeHandle(pthread_mutex_t* mutex) { 38 int result; 39 #if defined(DEBUG) 40 // Use an error checking mutex in debug mode. 41 pthread_mutexattr_t attr; 42 result = pthread_mutexattr_init(&attr); 43 ASSERT_EQ(0, result); 44 result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); 45 ASSERT_EQ(0, result); 46 result = pthread_mutex_init(mutex, &attr); 47 ASSERT_EQ(0, result); 48 result = pthread_mutexattr_destroy(&attr); 49 #else 50 // Use a fast mutex (default attributes). 51 result = pthread_mutex_init(mutex, NULL); 52 #endif // defined(DEBUG) 53 ASSERT_EQ(0, result); 54 USE(result); 55 } 56 57 58 static V8_INLINE void InitializeRecursiveNativeHandle(pthread_mutex_t* mutex) { 59 pthread_mutexattr_t attr; 60 int result = pthread_mutexattr_init(&attr); 61 ASSERT_EQ(0, result); 62 result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 63 ASSERT_EQ(0, result); 64 result = pthread_mutex_init(mutex, &attr); 65 ASSERT_EQ(0, result); 66 result = pthread_mutexattr_destroy(&attr); 67 ASSERT_EQ(0, result); 68 USE(result); 69 } 70 71 72 static V8_INLINE void DestroyNativeHandle(pthread_mutex_t* mutex) { 73 int result = pthread_mutex_destroy(mutex); 74 ASSERT_EQ(0, result); 75 USE(result); 76 } 77 78 79 static V8_INLINE void LockNativeHandle(pthread_mutex_t* mutex) { 80 int result = pthread_mutex_lock(mutex); 81 ASSERT_EQ(0, result); 82 USE(result); 83 } 84 85 86 static V8_INLINE void UnlockNativeHandle(pthread_mutex_t* mutex) { 87 int result = pthread_mutex_unlock(mutex); 88 ASSERT_EQ(0, result); 89 USE(result); 90 } 91 92 93 static V8_INLINE bool TryLockNativeHandle(pthread_mutex_t* mutex) { 94 int result = pthread_mutex_trylock(mutex); 95 if (result == EBUSY) { 96 return false; 97 } 98 ASSERT_EQ(0, result); 99 return true; 100 } 101 102 #elif V8_OS_WIN 103 104 static V8_INLINE void InitializeNativeHandle(PCRITICAL_SECTION cs) { 105 InitializeCriticalSection(cs); 106 } 107 108 109 static V8_INLINE void InitializeRecursiveNativeHandle(PCRITICAL_SECTION cs) { 110 InitializeCriticalSection(cs); 111 } 112 113 114 static V8_INLINE void DestroyNativeHandle(PCRITICAL_SECTION cs) { 115 DeleteCriticalSection(cs); 116 } 117 118 119 static V8_INLINE void LockNativeHandle(PCRITICAL_SECTION cs) { 120 EnterCriticalSection(cs); 121 } 122 123 124 static V8_INLINE void UnlockNativeHandle(PCRITICAL_SECTION cs) { 125 LeaveCriticalSection(cs); 126 } 127 128 129 static V8_INLINE bool TryLockNativeHandle(PCRITICAL_SECTION cs) { 130 return TryEnterCriticalSection(cs); 131 } 132 133 #endif // V8_OS_POSIX 134 135 136 Mutex::Mutex() { 137 InitializeNativeHandle(&native_handle_); 138 #ifdef DEBUG 139 level_ = 0; 140 #endif 141 } 142 143 144 Mutex::~Mutex() { 145 DestroyNativeHandle(&native_handle_); 146 ASSERT_EQ(0, level_); 147 } 148 149 150 void Mutex::Lock() { 151 LockNativeHandle(&native_handle_); 152 AssertUnheldAndMark(); 153 } 154 155 156 void Mutex::Unlock() { 157 AssertHeldAndUnmark(); 158 UnlockNativeHandle(&native_handle_); 159 } 160 161 162 bool Mutex::TryLock() { 163 if (!TryLockNativeHandle(&native_handle_)) { 164 return false; 165 } 166 AssertUnheldAndMark(); 167 return true; 168 } 169 170 171 RecursiveMutex::RecursiveMutex() { 172 InitializeRecursiveNativeHandle(&native_handle_); 173 #ifdef DEBUG 174 level_ = 0; 175 #endif 176 } 177 178 179 RecursiveMutex::~RecursiveMutex() { 180 DestroyNativeHandle(&native_handle_); 181 ASSERT_EQ(0, level_); 182 } 183 184 185 void RecursiveMutex::Lock() { 186 LockNativeHandle(&native_handle_); 187 #ifdef DEBUG 188 ASSERT_LE(0, level_); 189 level_++; 190 #endif 191 } 192 193 194 void RecursiveMutex::Unlock() { 195 #ifdef DEBUG 196 ASSERT_LT(0, level_); 197 level_--; 198 #endif 199 UnlockNativeHandle(&native_handle_); 200 } 201 202 203 bool RecursiveMutex::TryLock() { 204 if (!TryLockNativeHandle(&native_handle_)) { 205 return false; 206 } 207 #ifdef DEBUG 208 ASSERT_LE(0, level_); 209 level_++; 210 #endif 211 return true; 212 } 213 214 } } // namespace v8::internal 215