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 19TEST(ThreadSanitizer, SimpleWrite) { 20 ScopedThread t; 21 MemLoc l; 22 t.Write1(l); 23} 24 25TEST(ThreadSanitizer, SimpleWriteWrite) { 26 ScopedThread t1, t2; 27 MemLoc l1, l2; 28 t1.Write1(l1); 29 t2.Write1(l2); 30} 31 32TEST(ThreadSanitizer, WriteWriteRace) { 33 ScopedThread t1, t2; 34 MemLoc l; 35 t1.Write1(l); 36 t2.Write1(l, true); 37} 38 39TEST(ThreadSanitizer, ReadWriteRace) { 40 ScopedThread t1, t2; 41 MemLoc l; 42 t1.Read1(l); 43 t2.Write1(l, true); 44} 45 46TEST(ThreadSanitizer, WriteReadRace) { 47 ScopedThread t1, t2; 48 MemLoc l; 49 t1.Write1(l); 50 t2.Read1(l, true); 51} 52 53TEST(ThreadSanitizer, ReadReadNoRace) { 54 ScopedThread t1, t2; 55 MemLoc l; 56 t1.Read1(l); 57 t2.Read1(l); 58} 59 60TEST(ThreadSanitizer, WriteThenRead) { 61 MemLoc l; 62 ScopedThread t1, t2; 63 t1.Write1(l); 64 t1.Read1(l); 65 t2.Read1(l, true); 66} 67 68TEST(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 87TEST(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 107TEST(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 141TEST(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 155TEST(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 170TEST(ThreadSanitizer, RaceWithDeadThread) { 171 MemLoc l; 172 ScopedThread t; 173 ScopedThread().Write1(l); 174 t.Write1(l, true); 175} 176 177TEST(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 186TEST(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 195static void foo() { 196 volatile int x = 42; 197 int x2 = x; 198 (void)x2; 199} 200 201static void bar() { 202 volatile int x = 43; 203 int x2 = x; 204 (void)x2; 205} 206 207TEST(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 219struct ClassWithStatic { 220 static int Data[4]; 221}; 222 223int ClassWithStatic::Data[4]; 224 225static void foobarbaz() {} 226 227TEST(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