137 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of ThreadSanitizer (TSan), a race detector.10//11// Test utils.12//===----------------------------------------------------------------------===//13#ifndef TSAN_TEST_UTIL_H14#define TSAN_TEST_UTIL_H15 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 Spin45#else46 Spin = Normal47#endif48 };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_H137