1 //===-- tsan_mutex.cc -----------------------------------------------------===//
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 (TSan), a race detector.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "sanitizer_common/sanitizer_atomic.h"
14 #include "tsan_interface.h"
15 #include "tsan_interface_ann.h"
16 #include "tsan_test_util.h"
17 #include "gtest/gtest.h"
18 #include <stdint.h>
19
20 namespace __tsan {
21
TEST(ThreadSanitizer,BasicMutex)22 TEST(ThreadSanitizer, BasicMutex) {
23 ScopedThread t;
24 Mutex m;
25 t.Create(m);
26
27 t.Lock(m);
28 t.Unlock(m);
29
30 CHECK(t.TryLock(m));
31 t.Unlock(m);
32
33 t.Lock(m);
34 CHECK(!t.TryLock(m));
35 t.Unlock(m);
36
37 t.Destroy(m);
38 }
39
TEST(ThreadSanitizer,BasicSpinMutex)40 TEST(ThreadSanitizer, BasicSpinMutex) {
41 ScopedThread t;
42 Mutex m(Mutex::Spin);
43 t.Create(m);
44
45 t.Lock(m);
46 t.Unlock(m);
47
48 CHECK(t.TryLock(m));
49 t.Unlock(m);
50
51 t.Lock(m);
52 CHECK(!t.TryLock(m));
53 t.Unlock(m);
54
55 t.Destroy(m);
56 }
57
TEST(ThreadSanitizer,BasicRwMutex)58 TEST(ThreadSanitizer, BasicRwMutex) {
59 ScopedThread t;
60 Mutex m(Mutex::RW);
61 t.Create(m);
62
63 t.Lock(m);
64 t.Unlock(m);
65
66 CHECK(t.TryLock(m));
67 t.Unlock(m);
68
69 t.Lock(m);
70 CHECK(!t.TryLock(m));
71 t.Unlock(m);
72
73 t.ReadLock(m);
74 t.ReadUnlock(m);
75
76 CHECK(t.TryReadLock(m));
77 t.ReadUnlock(m);
78
79 t.Lock(m);
80 CHECK(!t.TryReadLock(m));
81 t.Unlock(m);
82
83 t.ReadLock(m);
84 CHECK(!t.TryLock(m));
85 t.ReadUnlock(m);
86
87 t.ReadLock(m);
88 CHECK(t.TryReadLock(m));
89 t.ReadUnlock(m);
90 t.ReadUnlock(m);
91
92 t.Destroy(m);
93 }
94
TEST(ThreadSanitizer,Mutex)95 TEST(ThreadSanitizer, Mutex) {
96 Mutex m;
97 MainThread t0;
98 t0.Create(m);
99
100 ScopedThread t1, t2;
101 MemLoc l;
102 t1.Lock(m);
103 t1.Write1(l);
104 t1.Unlock(m);
105 t2.Lock(m);
106 t2.Write1(l);
107 t2.Unlock(m);
108 t2.Destroy(m);
109 }
110
TEST(ThreadSanitizer,SpinMutex)111 TEST(ThreadSanitizer, SpinMutex) {
112 Mutex m(Mutex::Spin);
113 MainThread t0;
114 t0.Create(m);
115
116 ScopedThread t1, t2;
117 MemLoc l;
118 t1.Lock(m);
119 t1.Write1(l);
120 t1.Unlock(m);
121 t2.Lock(m);
122 t2.Write1(l);
123 t2.Unlock(m);
124 t2.Destroy(m);
125 }
126
TEST(ThreadSanitizer,RwMutex)127 TEST(ThreadSanitizer, RwMutex) {
128 Mutex m(Mutex::RW);
129 MainThread t0;
130 t0.Create(m);
131
132 ScopedThread t1, t2, t3;
133 MemLoc l;
134 t1.Lock(m);
135 t1.Write1(l);
136 t1.Unlock(m);
137 t2.Lock(m);
138 t2.Write1(l);
139 t2.Unlock(m);
140 t1.ReadLock(m);
141 t3.ReadLock(m);
142 t1.Read1(l);
143 t3.Read1(l);
144 t1.ReadUnlock(m);
145 t3.ReadUnlock(m);
146 t2.Lock(m);
147 t2.Write1(l);
148 t2.Unlock(m);
149 t2.Destroy(m);
150 }
151
TEST(ThreadSanitizer,StaticMutex)152 TEST(ThreadSanitizer, StaticMutex) {
153 // Emulates statically initialized mutex.
154 Mutex m;
155 m.StaticInit();
156 {
157 ScopedThread t1, t2;
158 t1.Lock(m);
159 t1.Unlock(m);
160 t2.Lock(m);
161 t2.Unlock(m);
162 }
163 MainThread().Destroy(m);
164 }
165
singleton_thread(void * param)166 static void *singleton_thread(void *param) {
167 atomic_uintptr_t *singleton = (atomic_uintptr_t *)param;
168 for (int i = 0; i < 4*1024*1024; i++) {
169 int *val = (int *)atomic_load(singleton, memory_order_acquire);
170 __tsan_acquire(singleton);
171 __tsan_read4(val);
172 CHECK_EQ(*val, 42);
173 }
174 return 0;
175 }
176
TEST(DISABLED_BENCH_ThreadSanitizer,Singleton)177 TEST(DISABLED_BENCH_ThreadSanitizer, Singleton) {
178 const int kClockSize = 100;
179 const int kThreadCount = 8;
180
181 // Puff off thread's clock.
182 for (int i = 0; i < kClockSize; i++) {
183 ScopedThread t1;
184 (void)t1;
185 }
186 // Create the singleton.
187 int val = 42;
188 __tsan_write4(&val);
189 atomic_uintptr_t singleton;
190 __tsan_release(&singleton);
191 atomic_store(&singleton, (uintptr_t)&val, memory_order_release);
192 // Create reader threads.
193 pthread_t threads[kThreadCount];
194 for (int t = 0; t < kThreadCount; t++)
195 pthread_create(&threads[t], 0, singleton_thread, &singleton);
196 for (int t = 0; t < kThreadCount; t++)
197 pthread_join(threads[t], 0);
198 }
199
TEST(DISABLED_BENCH_ThreadSanitizer,StopFlag)200 TEST(DISABLED_BENCH_ThreadSanitizer, StopFlag) {
201 const int kClockSize = 100;
202 const int kIters = 16*1024*1024;
203
204 // Puff off thread's clock.
205 for (int i = 0; i < kClockSize; i++) {
206 ScopedThread t1;
207 (void)t1;
208 }
209 // Create the stop flag.
210 atomic_uintptr_t flag;
211 __tsan_release(&flag);
212 atomic_store(&flag, 0, memory_order_release);
213 // Read it a lot.
214 for (int i = 0; i < kIters; i++) {
215 uptr v = atomic_load(&flag, memory_order_acquire);
216 __tsan_acquire(&flag);
217 CHECK_EQ(v, 0);
218 }
219 }
220
221 } // namespace __tsan
222