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
17void TestMutexBeforeInit();
18
19// A location of memory on which a race may be detected.
20class 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
32class 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.
60class 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
115class MainThread : public ScopedThread {
116 public:
117  MainThread()
118    : ScopedThread(false, true) {
119  }
120};
121
122#endif  // #ifndef TSAN_TEST_UTIL_H
123