File: tsan_test_util.h

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (136 lines) | stat: -rw-r--r-- 3,816 bytes parent folder | download | duplicates (18)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//===-- tsan_test_util.h ----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of ThreadSanitizer (TSan), a race detector.
//
// Test utils.
//===----------------------------------------------------------------------===//
#ifndef TSAN_TEST_UTIL_H
#define TSAN_TEST_UTIL_H

#include "gtest/gtest.h"

class ThreadSanitizer : public ::testing::Test {
 protected:
  void TearDown() override;
};

void TestMutexBeforeInit();

// A location of memory on which a race may be detected.
class MemLoc {
 public:
  explicit MemLoc(int offset_from_aligned = 0);
  explicit MemLoc(void *const real_addr) : loc_(real_addr) { }
  ~MemLoc();
  void *loc() const { return loc_; }
 private:
  void *const loc_;
  MemLoc(const MemLoc&);
  void operator = (const MemLoc&);
};

class UserMutex {
 public:
  enum Type {
    Normal,
    RW,
#ifndef __APPLE__
    Spin
#else
    Spin = Normal
#endif
  };

  explicit UserMutex(Type type = Normal);
  ~UserMutex();

  void Init();
  void StaticInit();  // Emulates static initialization (tsan invisible).
  void Destroy();
  void Lock();
  bool TryLock();
  void Unlock();
  void ReadLock();
  bool TryReadLock();
  void ReadUnlock();

 private:
  // Placeholder for pthread_mutex_t, CRITICAL_SECTION or whatever.
  void *mtx_[128];
  bool alive_;
  const Type type_;

  UserMutex(const UserMutex &);
  void operator=(const UserMutex &);
};

// A thread is started in CTOR and joined in DTOR.
class ScopedThread {
 public:
  explicit ScopedThread(bool detached = false, bool main = false);
  ~ScopedThread();
  void Detach();

  void Access(void *addr, bool is_write, int size, bool expect_race);
  void Read(const MemLoc &ml, int size, bool expect_race = false) {
    Access(ml.loc(), false, size, expect_race);
  }
  void Write(const MemLoc &ml, int size, bool expect_race = false) {
    Access(ml.loc(), true, size, expect_race);
  }
  void Read1(const MemLoc &ml, bool expect_race = false) {
    Read(ml, 1, expect_race); }
  void Read2(const MemLoc &ml, bool expect_race = false) {
    Read(ml, 2, expect_race); }
  void Read4(const MemLoc &ml, bool expect_race = false) {
    Read(ml, 4, expect_race); }
  void Read8(const MemLoc &ml, bool expect_race = false) {
    Read(ml, 8, expect_race); }
  void Write1(const MemLoc &ml, bool expect_race = false) {
    Write(ml, 1, expect_race); }
  void Write2(const MemLoc &ml, bool expect_race = false) {
    Write(ml, 2, expect_race); }
  void Write4(const MemLoc &ml, bool expect_race = false) {
    Write(ml, 4, expect_race); }
  void Write8(const MemLoc &ml, bool expect_race = false) {
    Write(ml, 8, expect_race); }

  void VptrUpdate(const MemLoc &vptr, const MemLoc &new_val,
                  bool expect_race = false);

  void Call(void(*pc)());
  void Return();

  void Create(const UserMutex &m);
  void Destroy(const UserMutex &m);
  void Lock(const UserMutex &m);
  bool TryLock(const UserMutex &m);
  void Unlock(const UserMutex &m);
  void ReadLock(const UserMutex &m);
  bool TryReadLock(const UserMutex &m);
  void ReadUnlock(const UserMutex &m);

  void Memcpy(void *dst, const void *src, int size, bool expect_race = false);
  void Memset(void *dst, int val, int size, bool expect_race = false);

 private:
  struct Impl;
  Impl *impl_;
  ScopedThread(const ScopedThread&);  // Not implemented.
  void operator = (const ScopedThread&);  // Not implemented.
};

class MainThread : public ScopedThread {
 public:
  MainThread()
    : ScopedThread(false, true) {
  }
};

#endif  // #ifndef TSAN_TEST_UTIL_H