]>
Commit | Line | Data |
---|---|---|
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); | |
23 | explicit MemLoc(void *const real_addr) : loc_(real_addr) { } | |
24 | ~MemLoc(); | |
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: | |
117 | MainThread() | |
118 | : ScopedThread(false, true) { | |
119 | } | |
120 | }; | |
121 | ||
122 | #endif // #ifndef TSAN_TEST_UTIL_H |