blob: 4d9c77961818787c1fa6499f77af5e13c934499e [file] [log] [blame]
Alexey Samsonov3b2f9f42012-06-04 13:55:19 +00001//===-- tsan_mutex.cc -----------------------------------------------------===//
Kostya Serebryanyff15ef02012-05-10 14:18:22 +00002//
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//===----------------------------------------------------------------------===//
Dmitry Vyukov6fa46f72012-06-29 16:58:33 +000013#include "sanitizer_common/sanitizer_atomic.h"
Kostya Serebryanyff15ef02012-05-10 14:18:22 +000014#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
20namespace __tsan {
21
22TEST(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
40TEST(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
58TEST(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
95TEST(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
111TEST(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
127TEST(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
152TEST(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
166static 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
177TEST(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
200TEST(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