blob: 6b6c25ddd54913fe3f99ff916d7cee14ba8a541a [file] [log] [blame]
Dmitry Vyukov7a9fa7d2012-06-29 17:10:08 +00001//===-- 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//===----------------------------------------------------------------------===//
Dmitry Vyukov513f0232012-06-29 17:32:18 +00009//
10// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11//
12//===----------------------------------------------------------------------===//
Dmitry Vyukov7a9fa7d2012-06-29 17:10:08 +000013
14#ifndef SANITIZER_MUTEX_H
15#define SANITIZER_MUTEX_H
16
Dmitry Vyukov7a9fa7d2012-06-29 17:10:08 +000017#include "sanitizer_atomic.h"
Dmitry Vyukovb13099c2012-07-02 07:09:21 +000018#include "sanitizer_internal_defs.h"
19#include "sanitizer_libc.h"
Dmitry Vyukov7a9fa7d2012-06-29 17:10:08 +000020
21namespace __sanitizer {
22
Dmitry Vyukovf4792872012-08-30 10:02:48 +000023class StaticSpinMutex {
Dmitry Vyukov513f0232012-06-29 17:32:18 +000024 public:
Dmitry Vyukovf4792872012-08-30 10:02:48 +000025 void Init() {
Dmitry Vyukov513f0232012-06-29 17:32:18 +000026 atomic_store(&state_, 0, memory_order_relaxed);
27 }
28
29 void Lock() {
Dmitry Vyukovb13099c2012-07-02 07:09:21 +000030 if (atomic_exchange(&state_, 1, memory_order_acquire) == 0)
31 return;
32 LockSlow();
Dmitry Vyukov513f0232012-06-29 17:32:18 +000033 }
34
35 void Unlock() {
36 atomic_store(&state_, 0, memory_order_release);
37 }
38
39 private:
40 atomic_uint8_t state_;
41
Dmitry Vyukovb13099c2012-07-02 07:09:21 +000042 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 }
Dmitry Vyukovf4792872012-08-30 10:02:48 +000053};
Dmitry Vyukovb13099c2012-07-02 07:09:21 +000054
Dmitry Vyukovf4792872012-08-30 10:02:48 +000055class SpinMutex : public StaticSpinMutex {
56 public:
57 SpinMutex() {
58 Init();
59 }
60
61 private:
Dmitry Vyukov513f0232012-06-29 17:32:18 +000062 SpinMutex(const SpinMutex&);
63 void operator=(const SpinMutex&);
64};
65
Dmitry Vyukov7a9fa7d2012-06-29 17:10:08 +000066template<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
Dmitry Vyukovf4792872012-08-30 10:02:48 +0000104typedef GenericScopedLock<StaticSpinMutex> SpinMutexLock;
Dmitry Vyukovb462dfc2012-07-02 06:54:24 +0000105
Dmitry Vyukov7a9fa7d2012-06-29 17:10:08 +0000106} // namespace __sanitizer
107
108#endif // SANITIZER_MUTEX_H