diff options
Diffstat (limited to 'lib/tsan/tests/rtl/tsan_test_util.h')
-rw-r--r-- | lib/tsan/tests/rtl/tsan_test_util.h | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/lib/tsan/tests/rtl/tsan_test_util.h b/lib/tsan/tests/rtl/tsan_test_util.h new file mode 100644 index 000000000000..483a564c8475 --- /dev/null +++ b/lib/tsan/tests/rtl/tsan_test_util.h @@ -0,0 +1,122 @@ +//===-- tsan_test_util.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +// Test utils. +//===----------------------------------------------------------------------===// +#ifndef TSAN_TEST_UTIL_H +#define TSAN_TEST_UTIL_H + +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 Mutex { + public: + enum Type { Normal, Spin, RW }; + + explicit Mutex(Type type = Normal); + ~Mutex(); + + void Init(); + void StaticInit(); // Emulates static initalization (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_; + + Mutex(const Mutex&); + void operator = (const Mutex&); +}; + +// 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 Mutex &m); + void Destroy(const Mutex &m); + void Lock(const Mutex &m); + bool TryLock(const Mutex &m); + void Unlock(const Mutex &m); + void ReadLock(const Mutex &m); + bool TryReadLock(const Mutex &m); + void ReadUnlock(const Mutex &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 |