1 //===-- tsan_mop.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 "tsan_interface.h" 14 #include "tsan_test_util.h" 15 #include "gtest/gtest.h" 16 #include <stddef.h> 17 #include <stdint.h> 18 19 TEST(ThreadSanitizer, SimpleWrite) { 20 ScopedThread t; 21 MemLoc l; 22 t.Write1(l); 23 } 24 25 TEST(ThreadSanitizer, SimpleWriteWrite) { 26 ScopedThread t1, t2; 27 MemLoc l1, l2; 28 t1.Write1(l1); 29 t2.Write1(l2); 30 } 31 32 TEST(ThreadSanitizer, WriteWriteRace) { 33 ScopedThread t1, t2; 34 MemLoc l; 35 t1.Write1(l); 36 t2.Write1(l, true); 37 } 38 39 TEST(ThreadSanitizer, ReadWriteRace) { 40 ScopedThread t1, t2; 41 MemLoc l; 42 t1.Read1(l); 43 t2.Write1(l, true); 44 } 45 46 TEST(ThreadSanitizer, WriteReadRace) { 47 ScopedThread t1, t2; 48 MemLoc l; 49 t1.Write1(l); 50 t2.Read1(l, true); 51 } 52 53 TEST(ThreadSanitizer, ReadReadNoRace) { 54 ScopedThread t1, t2; 55 MemLoc l; 56 t1.Read1(l); 57 t2.Read1(l); 58 } 59 60 TEST(ThreadSanitizer, WriteThenRead) { 61 MemLoc l; 62 ScopedThread t1, t2; 63 t1.Write1(l); 64 t1.Read1(l); 65 t2.Read1(l, true); 66 } 67 68 TEST(ThreadSanitizer, WriteThenLockedRead) { 69 Mutex m(Mutex::RW); 70 MainThread t0; 71 t0.Create(m); 72 MemLoc l; 73 { 74 ScopedThread t1, t2; 75 76 t1.Write8(l); 77 78 t1.Lock(m); 79 t1.Read8(l); 80 t1.Unlock(m); 81 82 t2.Read8(l, true); 83 } 84 t0.Destroy(m); 85 } 86 87 TEST(ThreadSanitizer, LockedWriteThenRead) { 88 Mutex m(Mutex::RW); 89 MainThread t0; 90 t0.Create(m); 91 MemLoc l; 92 { 93 ScopedThread t1, t2; 94 95 t1.Lock(m); 96 t1.Write8(l); 97 t1.Unlock(m); 98 99 t1.Read8(l); 100 101 t2.Read8(l, true); 102 } 103 t0.Destroy(m); 104 } 105 106 107 TEST(ThreadSanitizer, RaceWithOffset) { 108 ScopedThread t1, t2; 109 { 110 MemLoc l; 111 t1.Access(l.loc(), true, 8, false); 112 t2.Access((char*)l.loc() + 4, true, 4, true); 113 } 114 { 115 MemLoc l; 116 t1.Access(l.loc(), true, 8, false); 117 t2.Access((char*)l.loc() + 7, true, 1, true); 118 } 119 { 120 MemLoc l; 121 t1.Access((char*)l.loc() + 4, true, 4, false); 122 t2.Access((char*)l.loc() + 4, true, 2, true); 123 } 124 { 125 MemLoc l; 126 t1.Access((char*)l.loc() + 4, true, 4, false); 127 t2.Access((char*)l.loc() + 6, true, 2, true); 128 } 129 { 130 MemLoc l; 131 t1.Access((char*)l.loc() + 3, true, 2, false); 132 t2.Access((char*)l.loc() + 4, true, 1, true); 133 } 134 { 135 MemLoc l; 136 t1.Access((char*)l.loc() + 1, true, 8, false); 137 t2.Access((char*)l.loc() + 3, true, 1, true); 138 } 139 } 140 141 TEST(ThreadSanitizer, RaceWithOffset2) { 142 ScopedThread t1, t2; 143 { 144 MemLoc l; 145 t1.Access((char*)l.loc(), true, 4, false); 146 t2.Access((char*)l.loc() + 2, true, 1, true); 147 } 148 { 149 MemLoc l; 150 t1.Access((char*)l.loc() + 2, true, 1, false); 151 t2.Access((char*)l.loc(), true, 4, true); 152 } 153 } 154 155 TEST(ThreadSanitizer, NoRaceWithOffset) { 156 ScopedThread t1, t2; 157 { 158 MemLoc l; 159 t1.Access(l.loc(), true, 4, false); 160 t2.Access((char*)l.loc() + 4, true, 4, false); 161 } 162 { 163 MemLoc l; 164 t1.Access((char*)l.loc() + 3, true, 2, false); 165 t2.Access((char*)l.loc() + 1, true, 2, false); 166 t2.Access((char*)l.loc() + 5, true, 2, false); 167 } 168 } 169 170 TEST(ThreadSanitizer, RaceWithDeadThread) { 171 MemLoc l; 172 ScopedThread t; 173 ScopedThread().Write1(l); 174 t.Write1(l, true); 175 } 176 177 TEST(ThreadSanitizer, BenignRaceOnVptr) { 178 void *vptr_storage; 179 MemLoc vptr(&vptr_storage), val; 180 vptr_storage = val.loc(); 181 ScopedThread t1, t2; 182 t1.VptrUpdate(vptr, val); 183 t2.Read8(vptr); 184 } 185 186 TEST(ThreadSanitizer, HarmfulRaceOnVptr) { 187 void *vptr_storage; 188 MemLoc vptr(&vptr_storage), val1, val2; 189 vptr_storage = val1.loc(); 190 ScopedThread t1, t2; 191 t1.VptrUpdate(vptr, val2); 192 t2.Read8(vptr, true); 193 } 194 195 static void foo() { 196 volatile int x = 42; 197 int x2 = x; 198 (void)x2; 199 } 200 201 static void bar() { 202 volatile int x = 43; 203 int x2 = x; 204 (void)x2; 205 } 206 207 TEST(ThreadSanitizer, ReportDeadThread) { 208 MemLoc l; 209 ScopedThread t1; 210 { 211 ScopedThread t2; 212 t2.Call(&foo); 213 t2.Call(&bar); 214 t2.Write1(l); 215 } 216 t1.Write1(l, true); 217 } 218 219 struct ClassWithStatic { 220 static int Data[4]; 221 }; 222 223 int ClassWithStatic::Data[4]; 224 225 static void foobarbaz() {} 226 227 TEST(ThreadSanitizer, ReportRace) { 228 ScopedThread t1; 229 MainThread().Access(&ClassWithStatic::Data, true, 4, false); 230 t1.Call(&foobarbaz); 231 t1.Access(&ClassWithStatic::Data, true, 2, true); 232 t1.Return(); 233 } 234