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, NULL);
     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 #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   DCHECK_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   DCHECK_EQ(0, level_);
    159 }
    160 
    161 
    162 void RecursiveMutex::Lock() {
    163   LockNativeHandle(&native_handle_);
    164 #ifdef DEBUG
    165   DCHECK_LE(0, level_);
    166   level_++;
    167 #endif
    168 }
    169 
    170 
    171 void RecursiveMutex::Unlock() {
    172 #ifdef DEBUG
    173   DCHECK_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   DCHECK_LE(0, level_);
    186   level_++;
    187 #endif
    188   return true;
    189 }
    190 
    191 }  // namespace base
    192 }  // namespace v8
    193