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