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