blob: 675ad59b322c838caff0d4cce78e217b94fb8810 [file] [log] [blame]
Dmitry Vyukov8096a8c2017-03-26 15:27:04 +00001#include "test.h"
2#include <atomic>
3#include <vector>
4#include <sanitizer/tsan_interface.h>
5
6// A very primitive mutex annotated with tsan annotations.
7class Mutex {
8 public:
9 Mutex(bool prof = true)
10 : prof_(prof)
11 , locked_(false)
12 , seq_(0) {
13 __tsan_mutex_create(this, 0);
14 }
15
16 ~Mutex() {
17 __tsan_mutex_destroy(this, 0);
18 }
19
20 void Lock() {
21 __tsan_mutex_pre_lock(this, 0);
22 LockImpl();
23 __tsan_mutex_post_lock(this, 0, 0);
24 }
25
26 bool TryLock() {
27 __tsan_mutex_pre_lock(this, __tsan_mutex_try_lock);
28 bool ok = TryLockImpl();
29 __tsan_mutex_post_lock(this, __tsan_mutex_try_lock |
30 (ok ? 0 : __tsan_mutex_try_lock_failed), 0);
31 return ok;
32 }
33
34 void Unlock() {
35 __tsan_mutex_pre_unlock(this, 0);
36 UnlockImpl();
37 __tsan_mutex_post_unlock(this, 0);
38 }
39
40 void Wait() {
41 for (int seq = seq_; seq == seq_;) {
42 Unlock();
43 usleep(100);
44 Lock();
45 }
46 }
47
48 void Broadcast() {
49 __tsan_mutex_pre_signal(this, 0);
50 LockImpl(false);
51 seq_++;
52 UnlockImpl();
53 __tsan_mutex_post_signal(this, 0);
54 }
55
56 private:
57 const bool prof_;
58 std::atomic<bool> locked_;
59 int seq_;
60
61 // This models mutex profiling subsystem.
62 static Mutex prof_mu_;
63 static int prof_data_;
64
65 void LockImpl(bool prof = true) {
66 while (!TryLockImpl())
67 usleep(100);
68 if (prof && prof_)
69 Prof();
70 }
71
72 bool TryLockImpl() {
73 return !locked_.exchange(true);
74 }
75
76 void UnlockImpl() {
77 locked_.store(false);
78 }
79
80 void Prof() {
81 // This happens inside of mutex lock annotations.
82 __tsan_mutex_pre_divert(this, 0);
83 prof_mu_.Lock();
84 prof_data_++;
85 prof_mu_.Unlock();
86 __tsan_mutex_post_divert(this, 0);
87 }
88};
89
90Mutex Mutex::prof_mu_(false);
91int Mutex::prof_data_;