1 //===-- tsan_test_util.h ----------------------------------------*- C++ -*-===// 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 // Test utils. 13 //===----------------------------------------------------------------------===// 14 #ifndef TSAN_TEST_UTIL_H 15 #define TSAN_TEST_UTIL_H 16 17 void TestMutexBeforeInit(); 18 19 // A location of memory on which a race may be detected. 20 class MemLoc { 21 public: 22 explicit MemLoc(int offset_from_aligned = 0); MemLoc(void * const real_addr)23 explicit MemLoc(void *const real_addr) : loc_(real_addr) { } 24 ~MemLoc(); loc()25 void *loc() const { return loc_; } 26 private: 27 void *const loc_; 28 MemLoc(const MemLoc&); 29 void operator = (const MemLoc&); 30 }; 31 32 class Mutex { 33 public: 34 enum Type { 35 Normal, 36 RW, 37 #ifndef __APPLE__ 38 Spin 39 #else 40 Spin = Normal 41 #endif 42 }; 43 44 explicit Mutex(Type type = Normal); 45 ~Mutex(); 46 47 void Init(); 48 void StaticInit(); // Emulates static initialization (tsan invisible). 49 void Destroy(); 50 void Lock(); 51 bool TryLock(); 52 void Unlock(); 53 void ReadLock(); 54 bool TryReadLock(); 55 void ReadUnlock(); 56 57 private: 58 // Placeholder for pthread_mutex_t, CRITICAL_SECTION or whatever. 59 void *mtx_[128]; 60 bool alive_; 61 const Type type_; 62 63 Mutex(const Mutex&); 64 void operator = (const Mutex&); 65 }; 66 67 // A thread is started in CTOR and joined in DTOR. 68 class ScopedThread { 69 public: 70 explicit ScopedThread(bool detached = false, bool main = false); 71 ~ScopedThread(); 72 void Detach(); 73 74 void Access(void *addr, bool is_write, int size, bool expect_race); 75 void Read(const MemLoc &ml, int size, bool expect_race = false) { 76 Access(ml.loc(), false, size, expect_race); 77 } 78 void Write(const MemLoc &ml, int size, bool expect_race = false) { 79 Access(ml.loc(), true, size, expect_race); 80 } 81 void Read1(const MemLoc &ml, bool expect_race = false) { 82 Read(ml, 1, expect_race); } 83 void Read2(const MemLoc &ml, bool expect_race = false) { 84 Read(ml, 2, expect_race); } 85 void Read4(const MemLoc &ml, bool expect_race = false) { 86 Read(ml, 4, expect_race); } 87 void Read8(const MemLoc &ml, bool expect_race = false) { 88 Read(ml, 8, expect_race); } 89 void Write1(const MemLoc &ml, bool expect_race = false) { 90 Write(ml, 1, expect_race); } 91 void Write2(const MemLoc &ml, bool expect_race = false) { 92 Write(ml, 2, expect_race); } 93 void Write4(const MemLoc &ml, bool expect_race = false) { 94 Write(ml, 4, expect_race); } 95 void Write8(const MemLoc &ml, bool expect_race = false) { 96 Write(ml, 8, expect_race); } 97 98 void VptrUpdate(const MemLoc &vptr, const MemLoc &new_val, 99 bool expect_race = false); 100 101 void Call(void(*pc)()); 102 void Return(); 103 104 void Create(const Mutex &m); 105 void Destroy(const Mutex &m); 106 void Lock(const Mutex &m); 107 bool TryLock(const Mutex &m); 108 void Unlock(const Mutex &m); 109 void ReadLock(const Mutex &m); 110 bool TryReadLock(const Mutex &m); 111 void ReadUnlock(const Mutex &m); 112 113 void Memcpy(void *dst, const void *src, int size, bool expect_race = false); 114 void Memset(void *dst, int val, int size, bool expect_race = false); 115 116 private: 117 struct Impl; 118 Impl *impl_; 119 ScopedThread(const ScopedThread&); // Not implemented. 120 void operator = (const ScopedThread&); // Not implemented. 121 }; 122 123 class MainThread : public ScopedThread { 124 public: MainThread()125 MainThread() 126 : ScopedThread(false, true) { 127 } 128 }; 129 130 #endif // #ifndef TSAN_TEST_UTIL_H 131