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