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