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 { Normal, Spin, RW }; 35 36 explicit Mutex(Type type = Normal); 37 ~Mutex(); 38 39 void Init(); 40 void StaticInit(); // Emulates static initialization (tsan invisible). 41 void Destroy(); 42 void Lock(); 43 bool TryLock(); 44 void Unlock(); 45 void ReadLock(); 46 bool TryReadLock(); 47 void ReadUnlock(); 48 49 private: 50 // Placeholder for pthread_mutex_t, CRITICAL_SECTION or whatever. 51 void *mtx_[128]; 52 bool alive_; 53 const Type type_; 54 55 Mutex(const Mutex&); 56 void operator = (const Mutex&); 57 }; 58 59 // A thread is started in CTOR and joined in DTOR. 60 class ScopedThread { 61 public: 62 explicit ScopedThread(bool detached = false, bool main = false); 63 ~ScopedThread(); 64 void Detach(); 65 66 void Access(void *addr, bool is_write, int size, bool expect_race); 67 void Read(const MemLoc &ml, int size, bool expect_race = false) { 68 Access(ml.loc(), false, size, expect_race); 69 } 70 void Write(const MemLoc &ml, int size, bool expect_race = false) { 71 Access(ml.loc(), true, size, expect_race); 72 } 73 void Read1(const MemLoc &ml, bool expect_race = false) { 74 Read(ml, 1, expect_race); } 75 void Read2(const MemLoc &ml, bool expect_race = false) { 76 Read(ml, 2, expect_race); } 77 void Read4(const MemLoc &ml, bool expect_race = false) { 78 Read(ml, 4, expect_race); } 79 void Read8(const MemLoc &ml, bool expect_race = false) { 80 Read(ml, 8, expect_race); } 81 void Write1(const MemLoc &ml, bool expect_race = false) { 82 Write(ml, 1, expect_race); } 83 void Write2(const MemLoc &ml, bool expect_race = false) { 84 Write(ml, 2, expect_race); } 85 void Write4(const MemLoc &ml, bool expect_race = false) { 86 Write(ml, 4, expect_race); } 87 void Write8(const MemLoc &ml, bool expect_race = false) { 88 Write(ml, 8, expect_race); } 89 90 void VptrUpdate(const MemLoc &vptr, const MemLoc &new_val, 91 bool expect_race = false); 92 93 void Call(void(*pc)()); 94 void Return(); 95 96 void Create(const Mutex &m); 97 void Destroy(const Mutex &m); 98 void Lock(const Mutex &m); 99 bool TryLock(const Mutex &m); 100 void Unlock(const Mutex &m); 101 void ReadLock(const Mutex &m); 102 bool TryReadLock(const Mutex &m); 103 void ReadUnlock(const Mutex &m); 104 105 void Memcpy(void *dst, const void *src, int size, bool expect_race = false); 106 void Memset(void *dst, int val, int size, bool expect_race = false); 107 108 private: 109 struct Impl; 110 Impl *impl_; 111 ScopedThread(const ScopedThread&); // Not implemented. 112 void operator = (const ScopedThread&); // Not implemented. 113 }; 114 115 class MainThread : public ScopedThread { 116 public: MainThread()117 MainThread() 118 : ScopedThread(false, true) { 119 } 120 }; 121 122 #endif // #ifndef TSAN_TEST_UTIL_H 123