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 {
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.
68class 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
123class MainThread : public ScopedThread {
124 public:
125  MainThread()
126    : ScopedThread(false, true) {
127  }
128};
129
130#endif  // #ifndef TSAN_TEST_UTIL_H
131