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