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