xref: /openbsd-src/gnu/llvm/compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===-- tsan_test_util.h ----------------------------------------*- C++ -*-===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of ThreadSanitizer (TSan), a race detector.
103cab2bb3Spatrick //
113cab2bb3Spatrick // Test utils.
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick #ifndef TSAN_TEST_UTIL_H
143cab2bb3Spatrick #define TSAN_TEST_UTIL_H
153cab2bb3Spatrick 
16*810390e3Srobert #include "gtest/gtest.h"
17*810390e3Srobert 
18*810390e3Srobert class ThreadSanitizer : public ::testing::Test {
19*810390e3Srobert  protected:
20*810390e3Srobert   void TearDown() override;
21*810390e3Srobert };
22*810390e3Srobert 
233cab2bb3Spatrick void TestMutexBeforeInit();
243cab2bb3Spatrick 
253cab2bb3Spatrick // A location of memory on which a race may be detected.
263cab2bb3Spatrick class MemLoc {
273cab2bb3Spatrick  public:
283cab2bb3Spatrick   explicit MemLoc(int offset_from_aligned = 0);
MemLoc(void * const real_addr)293cab2bb3Spatrick   explicit MemLoc(void *const real_addr) : loc_(real_addr) { }
303cab2bb3Spatrick   ~MemLoc();
loc()313cab2bb3Spatrick   void *loc() const { return loc_; }
323cab2bb3Spatrick  private:
333cab2bb3Spatrick   void *const loc_;
343cab2bb3Spatrick   MemLoc(const MemLoc&);
353cab2bb3Spatrick   void operator = (const MemLoc&);
363cab2bb3Spatrick };
373cab2bb3Spatrick 
38d89ec533Spatrick class UserMutex {
393cab2bb3Spatrick  public:
403cab2bb3Spatrick   enum Type {
413cab2bb3Spatrick     Normal,
423cab2bb3Spatrick     RW,
433cab2bb3Spatrick #ifndef __APPLE__
443cab2bb3Spatrick     Spin
453cab2bb3Spatrick #else
463cab2bb3Spatrick     Spin = Normal
473cab2bb3Spatrick #endif
483cab2bb3Spatrick   };
493cab2bb3Spatrick 
50d89ec533Spatrick   explicit UserMutex(Type type = Normal);
51d89ec533Spatrick   ~UserMutex();
523cab2bb3Spatrick 
533cab2bb3Spatrick   void Init();
543cab2bb3Spatrick   void StaticInit();  // Emulates static initialization (tsan invisible).
553cab2bb3Spatrick   void Destroy();
563cab2bb3Spatrick   void Lock();
573cab2bb3Spatrick   bool TryLock();
583cab2bb3Spatrick   void Unlock();
593cab2bb3Spatrick   void ReadLock();
603cab2bb3Spatrick   bool TryReadLock();
613cab2bb3Spatrick   void ReadUnlock();
623cab2bb3Spatrick 
633cab2bb3Spatrick  private:
643cab2bb3Spatrick   // Placeholder for pthread_mutex_t, CRITICAL_SECTION or whatever.
653cab2bb3Spatrick   void *mtx_[128];
663cab2bb3Spatrick   bool alive_;
673cab2bb3Spatrick   const Type type_;
683cab2bb3Spatrick 
69d89ec533Spatrick   UserMutex(const UserMutex &);
70d89ec533Spatrick   void operator=(const UserMutex &);
713cab2bb3Spatrick };
723cab2bb3Spatrick 
733cab2bb3Spatrick // A thread is started in CTOR and joined in DTOR.
743cab2bb3Spatrick class ScopedThread {
753cab2bb3Spatrick  public:
763cab2bb3Spatrick   explicit ScopedThread(bool detached = false, bool main = false);
773cab2bb3Spatrick   ~ScopedThread();
783cab2bb3Spatrick   void Detach();
793cab2bb3Spatrick 
803cab2bb3Spatrick   void Access(void *addr, bool is_write, int size, bool expect_race);
813cab2bb3Spatrick   void Read(const MemLoc &ml, int size, bool expect_race = false) {
823cab2bb3Spatrick     Access(ml.loc(), false, size, expect_race);
833cab2bb3Spatrick   }
843cab2bb3Spatrick   void Write(const MemLoc &ml, int size, bool expect_race = false) {
853cab2bb3Spatrick     Access(ml.loc(), true, size, expect_race);
863cab2bb3Spatrick   }
873cab2bb3Spatrick   void Read1(const MemLoc &ml, bool expect_race = false) {
883cab2bb3Spatrick     Read(ml, 1, expect_race); }
893cab2bb3Spatrick   void Read2(const MemLoc &ml, bool expect_race = false) {
903cab2bb3Spatrick     Read(ml, 2, expect_race); }
913cab2bb3Spatrick   void Read4(const MemLoc &ml, bool expect_race = false) {
923cab2bb3Spatrick     Read(ml, 4, expect_race); }
933cab2bb3Spatrick   void Read8(const MemLoc &ml, bool expect_race = false) {
943cab2bb3Spatrick     Read(ml, 8, expect_race); }
953cab2bb3Spatrick   void Write1(const MemLoc &ml, bool expect_race = false) {
963cab2bb3Spatrick     Write(ml, 1, expect_race); }
973cab2bb3Spatrick   void Write2(const MemLoc &ml, bool expect_race = false) {
983cab2bb3Spatrick     Write(ml, 2, expect_race); }
993cab2bb3Spatrick   void Write4(const MemLoc &ml, bool expect_race = false) {
1003cab2bb3Spatrick     Write(ml, 4, expect_race); }
1013cab2bb3Spatrick   void Write8(const MemLoc &ml, bool expect_race = false) {
1023cab2bb3Spatrick     Write(ml, 8, expect_race); }
1033cab2bb3Spatrick 
1043cab2bb3Spatrick   void VptrUpdate(const MemLoc &vptr, const MemLoc &new_val,
1053cab2bb3Spatrick                   bool expect_race = false);
1063cab2bb3Spatrick 
1073cab2bb3Spatrick   void Call(void(*pc)());
1083cab2bb3Spatrick   void Return();
1093cab2bb3Spatrick 
110d89ec533Spatrick   void Create(const UserMutex &m);
111d89ec533Spatrick   void Destroy(const UserMutex &m);
112d89ec533Spatrick   void Lock(const UserMutex &m);
113d89ec533Spatrick   bool TryLock(const UserMutex &m);
114d89ec533Spatrick   void Unlock(const UserMutex &m);
115d89ec533Spatrick   void ReadLock(const UserMutex &m);
116d89ec533Spatrick   bool TryReadLock(const UserMutex &m);
117d89ec533Spatrick   void ReadUnlock(const UserMutex &m);
1183cab2bb3Spatrick 
1193cab2bb3Spatrick   void Memcpy(void *dst, const void *src, int size, bool expect_race = false);
1203cab2bb3Spatrick   void Memset(void *dst, int val, int size, bool expect_race = false);
1213cab2bb3Spatrick 
1223cab2bb3Spatrick  private:
1233cab2bb3Spatrick   struct Impl;
1243cab2bb3Spatrick   Impl *impl_;
1253cab2bb3Spatrick   ScopedThread(const ScopedThread&);  // Not implemented.
1263cab2bb3Spatrick   void operator = (const ScopedThread&);  // Not implemented.
1273cab2bb3Spatrick };
1283cab2bb3Spatrick 
1293cab2bb3Spatrick class MainThread : public ScopedThread {
1303cab2bb3Spatrick  public:
MainThread()1313cab2bb3Spatrick   MainThread()
1323cab2bb3Spatrick     : ScopedThread(false, true) {
1333cab2bb3Spatrick   }
1343cab2bb3Spatrick };
1353cab2bb3Spatrick 
1363cab2bb3Spatrick #endif  // #ifndef TSAN_TEST_UTIL_H
137