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