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