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 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 222