Home | History | Annotate | Download | only in platform
      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