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: 25 void Init() { 26 atomic_store(&state_, 0, memory_order_relaxed); 27 } 28 29 void Lock() { 30 if (TryLock()) 31 return; 32 LockSlow(); 33 } 34 35 bool TryLock() { 36 return atomic_exchange(&state_, 1, memory_order_acquire) == 0; 37 } 38 39 void Unlock() { 40 atomic_store(&state_, 0, memory_order_release); 41 } 42 43 private: 44 atomic_uint8_t state_; 45 46 void NOINLINE LockSlow() { 47 for (int i = 0;; i++) { 48 if (i < 10) 49 proc_yield(10); 50 else 51 internal_sched_yield(); 52 if (atomic_load(&state_, memory_order_relaxed) == 0 53 && atomic_exchange(&state_, 1, memory_order_acquire) == 0) 54 return; 55 } 56 } 57 }; 58 59 class SpinMutex : public StaticSpinMutex { 60 public: 61 SpinMutex() { 62 Init(); 63 } 64 65 private: 66 SpinMutex(const SpinMutex&); 67 void operator=(const SpinMutex&); 68 }; 69 70 class BlockingMutex { 71 public: 72 explicit BlockingMutex(LinkerInitialized); 73 BlockingMutex(); 74 void Lock(); 75 void Unlock(); 76 void CheckLocked(); 77 private: 78 uptr opaque_storage_[10]; 79 uptr owner_; // for debugging 80 }; 81 82 template<typename MutexType> 83 class GenericScopedLock { 84 public: 85 explicit GenericScopedLock(MutexType *mu) 86 : mu_(mu) { 87 mu_->Lock(); 88 } 89 90 ~GenericScopedLock() { 91 mu_->Unlock(); 92 } 93 94 private: 95 MutexType *mu_; 96 97 GenericScopedLock(const GenericScopedLock&); 98 void operator=(const GenericScopedLock&); 99 }; 100 101 template<typename MutexType> 102 class GenericScopedReadLock { 103 public: 104 explicit GenericScopedReadLock(MutexType *mu) 105 : mu_(mu) { 106 mu_->ReadLock(); 107 } 108 109 ~GenericScopedReadLock() { 110 mu_->ReadUnlock(); 111 } 112 113 private: 114 MutexType *mu_; 115 116 GenericScopedReadLock(const GenericScopedReadLock&); 117 void operator=(const GenericScopedReadLock&); 118 }; 119 120 typedef GenericScopedLock<StaticSpinMutex> SpinMutexLock; 121 typedef GenericScopedLock<BlockingMutex> BlockingMutexLock; 122 123 } // namespace __sanitizer 124 125 #endif // SANITIZER_MUTEX_H 126