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