1 //===-- sanitizer_mutex.h ---------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef SANITIZER_MUTEX_H 15 #define SANITIZER_MUTEX_H 16 17 #include "sanitizer_atomic.h" 18 #include "sanitizer_internal_defs.h" 19 #include "sanitizer_libc.h" 20 21 namespace __sanitizer { 22 23 class StaticSpinMutex { 24 public: Init()25 void Init() { 26 atomic_store(&state_, 0, memory_order_relaxed); 27 } 28 Lock()29 void Lock() { 30 if (atomic_exchange(&state_, 1, memory_order_acquire) == 0) 31 return; 32 LockSlow(); 33 } 34 Unlock()35 void Unlock() { 36 atomic_store(&state_, 0, memory_order_release); 37 } 38 39 private: 40 atomic_uint8_t state_; 41 LockSlow()42 void NOINLINE LockSlow() { 43 for (int i = 0;; i++) { 44 if (i < 10) 45 proc_yield(10); 46 else 47 internal_sched_yield(); 48 if (atomic_load(&state_, memory_order_relaxed) == 0 49 && atomic_exchange(&state_, 1, memory_order_acquire) == 0) 50 return; 51 } 52 } 53 }; 54 55 class SpinMutex : public StaticSpinMutex { 56 public: SpinMutex()57 SpinMutex() { 58 Init(); 59 } 60 61 private: 62 SpinMutex(const SpinMutex&); 63 void operator=(const SpinMutex&); 64 }; 65 66 template<typename MutexType> 67 class GenericScopedLock { 68 public: GenericScopedLock(MutexType * mu)69 explicit GenericScopedLock(MutexType *mu) 70 : mu_(mu) { 71 mu_->Lock(); 72 } 73 ~GenericScopedLock()74 ~GenericScopedLock() { 75 mu_->Unlock(); 76 } 77 78 private: 79 MutexType *mu_; 80 81 GenericScopedLock(const GenericScopedLock&); 82 void operator=(const GenericScopedLock&); 83 }; 84 85 template<typename MutexType> 86 class GenericScopedReadLock { 87 public: GenericScopedReadLock(MutexType * mu)88 explicit GenericScopedReadLock(MutexType *mu) 89 : mu_(mu) { 90 mu_->ReadLock(); 91 } 92 ~GenericScopedReadLock()93 ~GenericScopedReadLock() { 94 mu_->ReadUnlock(); 95 } 96 97 private: 98 MutexType *mu_; 99 100 GenericScopedReadLock(const GenericScopedReadLock&); 101 void operator=(const GenericScopedReadLock&); 102 }; 103 104 typedef GenericScopedLock<StaticSpinMutex> SpinMutexLock; 105 106 } // namespace __sanitizer 107 108 #endif // SANITIZER_MUTEX_H 109