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