diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h b/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h @@ -149,9 +149,9 @@ }; // Reader-writer mutex. -class MUTEX Mutex2 { +class MUTEX Mutex { public: - constexpr Mutex2(MutexType type = MutexUnchecked) : checked_(type) {} + constexpr Mutex(MutexType type = MutexUnchecked) : checked_(type) {} void Lock() ACQUIRE() { checked_.Lock(); @@ -329,8 +329,8 @@ static constexpr u64 kWriterLock = 1ull << (3 * kCounterWidth); static constexpr u64 kWriterSpinWait = 1ull << (3 * kCounterWidth + 1); - Mutex2(const Mutex2 &) = delete; - void operator=(const Mutex2 &) = delete; + Mutex(const Mutex &) = delete; + void operator=(const Mutex &) = delete; }; void FutexWait(atomic_uint32_t *p, u32 cmp); @@ -477,6 +477,8 @@ typedef GenericScopedLock BlockingMutexLock; typedef GenericScopedLock RWMutexLock; typedef GenericScopedReadLock RWMutexReadLock; +typedef GenericScopedLock Lock; +typedef GenericScopedReadLock ReadLock; } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp @@ -158,12 +158,12 @@ check_locked(mtx); } -TEST(SanitizerCommon, Mutex2) { - Mutex2 mtx; - TestData data(&mtx); +TEST(SanitizerCommon, Mutex) { + Mutex mtx; + TestData data(&mtx); pthread_t threads[kThreads]; for (int i = 0; i < kThreads; i++) - PTHREAD_CREATE(&threads[i], 0, read_write_thread, &data); + PTHREAD_CREATE(&threads[i], 0, read_write_thread, &data); for (int i = 0; i < kThreads; i++) PTHREAD_JOIN(threads[i], 0); } diff --git a/compiler-rt/lib/tsan/CMakeLists.txt b/compiler-rt/lib/tsan/CMakeLists.txt --- a/compiler-rt/lib/tsan/CMakeLists.txt +++ b/compiler-rt/lib/tsan/CMakeLists.txt @@ -39,7 +39,6 @@ rtl/tsan_malloc_mac.cpp rtl/tsan_md5.cpp rtl/tsan_mman.cpp - rtl/tsan_mutex.cpp rtl/tsan_mutexset.cpp rtl/tsan_preinit.cpp rtl/tsan_report.cpp @@ -94,7 +93,6 @@ rtl/tsan_interface_inl.h rtl/tsan_interface_java.h rtl/tsan_mman.h - rtl/tsan_mutex.h rtl/tsan_mutexset.h rtl/tsan_platform.h rtl/tsan_ppc_regs.h diff --git a/compiler-rt/lib/tsan/go/build.bat b/compiler-rt/lib/tsan/go/build.bat --- a/compiler-rt/lib/tsan/go/build.bat +++ b/compiler-rt/lib/tsan/go/build.bat @@ -4,7 +4,6 @@ ..\rtl\tsan_clock.cpp ^ ..\rtl\tsan_flags.cpp ^ ..\rtl\tsan_md5.cpp ^ - ..\rtl\tsan_mutex.cpp ^ ..\rtl\tsan_report.cpp ^ ..\rtl\tsan_rtl.cpp ^ ..\rtl\tsan_rtl_mutex.cpp ^ diff --git a/compiler-rt/lib/tsan/go/buildgo.sh b/compiler-rt/lib/tsan/go/buildgo.sh --- a/compiler-rt/lib/tsan/go/buildgo.sh +++ b/compiler-rt/lib/tsan/go/buildgo.sh @@ -9,7 +9,6 @@ ../rtl/tsan_flags.cpp ../rtl/tsan_interface_atomic.cpp ../rtl/tsan_md5.cpp - ../rtl/tsan_mutex.cpp ../rtl/tsan_report.cpp ../rtl/tsan_rtl.cpp ../rtl/tsan_rtl_mutex.cpp diff --git a/compiler-rt/lib/tsan/rtl/tsan_defs.h b/compiler-rt/lib/tsan/rtl/tsan_defs.h --- a/compiler-rt/lib/tsan/rtl/tsan_defs.h +++ b/compiler-rt/lib/tsan/rtl/tsan_defs.h @@ -15,6 +15,7 @@ #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_mutex.h" #include "ubsan/ubsan_platform.h" // Setup defaults for compile definitions. @@ -172,6 +173,17 @@ // as 16-bit values, see tsan_defs.h. }; +enum MutexType { + MutexTypeTrace = MutexLastCommon, + MutexTypeReport, + MutexTypeSyncVar, + MutexTypeAnnotations, + MutexTypeAtExit, + MutexTypeFired, + MutexTypeRacy, + MutexTypeGlobalProc, +}; + } // namespace __tsan #endif // TSAN_DEFS_H diff --git a/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h b/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h --- a/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h +++ b/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h @@ -20,7 +20,6 @@ #include "sanitizer_common/sanitizer_common.h" #include "tsan_defs.h" -#include "tsan_mutex.h" namespace __tsan { diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -267,7 +267,7 @@ if (!thr_->ignore_interceptors) { ProcessPendingSignals(thr_); FuncExit(thr_); - CheckNoLocks(thr_); + CheckedMutex::CheckNoLocks(); } } diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp b/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp @@ -15,7 +15,6 @@ #include "sanitizer_common/sanitizer_stacktrace.h" #include "sanitizer_common/sanitizer_vector.h" #include "tsan_interface_ann.h" -#include "tsan_mutex.h" #include "tsan_report.h" #include "tsan_rtl.h" #include "tsan_mman.h" @@ -38,7 +37,7 @@ ~ScopedAnnotation() { FuncExit(thr_); - CheckNoLocks(thr_); + CheckedMutex::CheckNoLocks(); } private: ThreadState *const thr_; diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp b/compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp @@ -12,7 +12,6 @@ #include "tsan_interface_java.h" #include "tsan_rtl.h" -#include "tsan_mutex.h" #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_placement_new.h" diff --git a/compiler-rt/lib/tsan/rtl/tsan_mutex.h b/compiler-rt/lib/tsan/rtl/tsan_mutex.h deleted file mode 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_mutex.h +++ /dev/null @@ -1,87 +0,0 @@ -//===-- tsan_mutex.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. -// -//===----------------------------------------------------------------------===// -#ifndef TSAN_MUTEX_H -#define TSAN_MUTEX_H - -#include "sanitizer_common/sanitizer_atomic.h" -#include "sanitizer_common/sanitizer_mutex.h" -#include "tsan_defs.h" - -namespace __tsan { - -enum MutexType { - MutexTypeInvalid, - MutexTypeTrace, - MutexTypeThreads, - MutexTypeReport, - MutexTypeSyncVar, - MutexTypeSyncTab, - MutexTypeSlab, - MutexTypeAnnotations, - MutexTypeAtExit, - MutexTypeMBlock, - MutexTypeJavaMBlock, - MutexTypeDDetector, - MutexTypeFired, - MutexTypeRacy, - MutexTypeGlobalProc, - - // This must be the last. - MutexTypeCount -}; - -class Mutex { - public: - explicit Mutex(MutexType type); - ~Mutex(); - - void Lock(); - void Unlock(); - - void ReadLock(); - void ReadUnlock(); - - void CheckLocked(); - - private: - atomic_uintptr_t state_; -#if SANITIZER_DEBUG - MutexType type_; -#endif - - Mutex(const Mutex&); - void operator = (const Mutex&); -}; - -typedef GenericScopedLock Lock; -typedef GenericScopedReadLock ReadLock; - -class InternalDeadlockDetector { - public: - InternalDeadlockDetector(); - void Lock(MutexType t); - void Unlock(MutexType t); - void CheckNoLocks(); - private: - u64 seq_; - u64 locked_[MutexTypeCount]; -}; - -void InitializeMutex(); - -// Checks that the current thread does not hold any runtime locks -// (e.g. when returning from an interceptor). -void CheckNoLocks(ThreadState *thr); - -} // namespace __tsan - -#endif // TSAN_MUTEX_H diff --git a/compiler-rt/lib/tsan/rtl/tsan_mutex.cpp b/compiler-rt/lib/tsan/rtl/tsan_mutex.cpp deleted file mode 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_mutex.cpp +++ /dev/null @@ -1,280 +0,0 @@ -//===-- tsan_mutex.cpp ----------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_libc.h" -#include "tsan_mutex.h" -#include "tsan_platform.h" -#include "tsan_rtl.h" - -namespace __tsan { - -// Simple reader-writer spin-mutex. Optimized for not-so-contended case. -// Readers have preference, can possibly starvate writers. - -// The table fixes what mutexes can be locked under what mutexes. -// E.g. if the row for MutexTypeThreads contains MutexTypeReport, -// then Report mutex can be locked while under Threads mutex. -// The leaf mutexes can be locked under any other mutexes. -// Recursive locking is not supported. -#if SANITIZER_DEBUG && !SANITIZER_GO -const MutexType MutexTypeLeaf = (MutexType)-1; -static MutexType CanLockTab[MutexTypeCount][MutexTypeCount] = { - /*0 MutexTypeInvalid*/ {}, - /*1 MutexTypeTrace*/ {MutexTypeLeaf}, - /*2 MutexTypeThreads*/ {MutexTypeReport}, - /*3 MutexTypeReport*/ {MutexTypeSyncVar, - MutexTypeMBlock, MutexTypeJavaMBlock}, - /*4 MutexTypeSyncVar*/ {MutexTypeDDetector}, - /*5 MutexTypeSyncTab*/ {}, // unused - /*6 MutexTypeSlab*/ {MutexTypeLeaf}, - /*7 MutexTypeAnnotations*/ {}, - /*8 MutexTypeAtExit*/ {MutexTypeSyncVar}, - /*9 MutexTypeMBlock*/ {MutexTypeSyncVar}, - /*10 MutexTypeJavaMBlock*/ {MutexTypeSyncVar}, - /*11 MutexTypeDDetector*/ {}, - /*12 MutexTypeFired*/ {MutexTypeLeaf}, - /*13 MutexTypeRacy*/ {MutexTypeLeaf}, - /*14 MutexTypeGlobalProc*/ {}, -}; - -static bool CanLockAdj[MutexTypeCount][MutexTypeCount]; -#endif - -void InitializeMutex() { -#if SANITIZER_DEBUG && !SANITIZER_GO - // Build the "can lock" adjacency matrix. - // If [i][j]==true, then one can lock mutex j while under mutex i. - const int N = MutexTypeCount; - int cnt[N] = {}; - bool leaf[N] = {}; - for (int i = 1; i < N; i++) { - for (int j = 0; j < N; j++) { - MutexType z = CanLockTab[i][j]; - if (z == MutexTypeInvalid) - continue; - if (z == MutexTypeLeaf) { - CHECK(!leaf[i]); - leaf[i] = true; - continue; - } - CHECK(!CanLockAdj[i][(int)z]); - CanLockAdj[i][(int)z] = true; - cnt[i]++; - } - } - for (int i = 0; i < N; i++) { - CHECK(!leaf[i] || cnt[i] == 0); - } - // Add leaf mutexes. - for (int i = 0; i < N; i++) { - if (!leaf[i]) - continue; - for (int j = 0; j < N; j++) { - if (i == j || leaf[j] || j == MutexTypeInvalid) - continue; - CHECK(!CanLockAdj[j][i]); - CanLockAdj[j][i] = true; - } - } - // Build the transitive closure. - bool CanLockAdj2[MutexTypeCount][MutexTypeCount]; - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - CanLockAdj2[i][j] = CanLockAdj[i][j]; - } - } - for (int k = 0; k < N; k++) { - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - if (CanLockAdj2[i][k] && CanLockAdj2[k][j]) { - CanLockAdj2[i][j] = true; - } - } - } - } -#if 0 - Printf("Can lock graph:\n"); - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - Printf("%d ", CanLockAdj[i][j]); - } - Printf("\n"); - } - Printf("Can lock graph closure:\n"); - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - Printf("%d ", CanLockAdj2[i][j]); - } - Printf("\n"); - } -#endif - // Verify that the graph is acyclic. - for (int i = 0; i < N; i++) { - if (CanLockAdj2[i][i]) { - Printf("Mutex %d participates in a cycle\n", i); - Die(); - } - } -#endif -} - -InternalDeadlockDetector::InternalDeadlockDetector() { - // Rely on zero initialization because some mutexes can be locked before ctor. -} - -#if SANITIZER_DEBUG && !SANITIZER_GO -void InternalDeadlockDetector::Lock(MutexType t) { - // Printf("LOCK %d @%zu\n", t, seq_ + 1); - CHECK_GT(t, MutexTypeInvalid); - CHECK_LT(t, MutexTypeCount); - u64 max_seq = 0; - u64 max_idx = MutexTypeInvalid; - for (int i = 0; i != MutexTypeCount; i++) { - if (locked_[i] == 0) - continue; - CHECK_NE(locked_[i], max_seq); - if (max_seq < locked_[i]) { - max_seq = locked_[i]; - max_idx = i; - } - } - locked_[t] = ++seq_; - if (max_idx == MutexTypeInvalid) - return; - // Printf(" last %d @%zu\n", max_idx, max_seq); - if (!CanLockAdj[max_idx][t]) { - Printf("ThreadSanitizer: internal deadlock detected\n"); - Printf("ThreadSanitizer: can't lock %d while under %zu\n", - t, (uptr)max_idx); - CHECK(0); - } -} - -void InternalDeadlockDetector::Unlock(MutexType t) { - // Printf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]); - CHECK(locked_[t]); - locked_[t] = 0; -} - -void InternalDeadlockDetector::CheckNoLocks() { - for (int i = 0; i != MutexTypeCount; i++) { - CHECK_EQ(locked_[i], 0); - } -} -#endif - -void CheckNoLocks(ThreadState *thr) { -#if SANITIZER_DEBUG && !SANITIZER_GO - thr->internal_deadlock_detector.CheckNoLocks(); -#endif -} - -const uptr kUnlocked = 0; -const uptr kWriteLock = 1; -const uptr kReadLock = 2; - -class Backoff { - public: - Backoff() - : iter_() { - } - - bool Do() { - if (iter_++ < kActiveSpinIters) - proc_yield(kActiveSpinCnt); - else - internal_sched_yield(); - return true; - } - - u64 Contention() const { - u64 active = iter_ % kActiveSpinIters; - u64 passive = iter_ - active; - return active + 10 * passive; - } - - private: - int iter_; - static const int kActiveSpinIters = 10; - static const int kActiveSpinCnt = 20; -}; - -Mutex::Mutex(MutexType type) { - CHECK_GT(type, MutexTypeInvalid); - CHECK_LT(type, MutexTypeCount); -#if SANITIZER_DEBUG - type_ = type; -#endif - atomic_store(&state_, kUnlocked, memory_order_relaxed); -} - -Mutex::~Mutex() { - CHECK_EQ(atomic_load(&state_, memory_order_relaxed), kUnlocked); -} - -void Mutex::Lock() { -#if SANITIZER_DEBUG && !SANITIZER_GO - cur_thread()->internal_deadlock_detector.Lock(type_); -#endif - uptr cmp = kUnlocked; - if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock, - memory_order_acquire)) - return; - for (Backoff backoff; backoff.Do();) { - if (atomic_load(&state_, memory_order_relaxed) == kUnlocked) { - cmp = kUnlocked; - if (atomic_compare_exchange_weak(&state_, &cmp, kWriteLock, - memory_order_acquire)) { - return; - } - } - } -} - -void Mutex::Unlock() { - uptr prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release); - (void)prev; - DCHECK_NE(prev & kWriteLock, 0); -#if SANITIZER_DEBUG && !SANITIZER_GO - cur_thread()->internal_deadlock_detector.Unlock(type_); -#endif -} - -void Mutex::ReadLock() { -#if SANITIZER_DEBUG && !SANITIZER_GO - cur_thread()->internal_deadlock_detector.Lock(type_); -#endif - uptr prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire); - if ((prev & kWriteLock) == 0) - return; - for (Backoff backoff; backoff.Do();) { - prev = atomic_load(&state_, memory_order_acquire); - if ((prev & kWriteLock) == 0) { - return; - } - } -} - -void Mutex::ReadUnlock() { - uptr prev = atomic_fetch_sub(&state_, kReadLock, memory_order_release); - (void)prev; - DCHECK_EQ(prev & kWriteLock, 0); - DCHECK_GT(prev & ~kWriteLock, 0); -#if SANITIZER_DEBUG && !SANITIZER_GO - cur_thread()->internal_deadlock_detector.Unlock(type_); -#endif -} - -void Mutex::CheckLocked() { - CHECK_NE(atomic_load(&state_, memory_order_relaxed), 0); -} - -} // namespace __tsan diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp @@ -422,7 +422,6 @@ InitializeInterceptors(); CheckShadowMapping(); InitializePlatform(); - InitializeMutex(); InitializeDynamicAnnotations(); #if !SANITIZER_GO InitializeShadowMemory(); @@ -1133,7 +1132,28 @@ } // namespace __tsan +#if SANITIZER_CHECK_DEADLOCKS +namespace __sanitizer { +using namespace __tsan; +MutexMeta mutex_meta[] = { + {MutexInvalid, "Invalid", {}}, + {MutexThreadRegistry, "ThreadRegistry", {}}, + {MutexTypeTrace, "Trace", {MutexLeaf}}, + {MutexTypeReport, "Report", {MutexTypeSyncVar}}, + {MutexTypeSyncVar, "SyncVar", {}}, + {MutexTypeAnnotations, "Annotations", {}}, + {MutexTypeAtExit, "AtExit", {MutexTypeSyncVar}}, + {MutexTypeFired, "Fired", {MutexLeaf}}, + {MutexTypeRacy, "Racy", {MutexLeaf}}, + {MutexTypeGlobalProc, "GlobalProc", {}}, + {}, +}; + +void PrintMutexPC(uptr pc) { StackTrace(&pc, 1).Print(); } +} // namespace __sanitizer +#endif + #if !SANITIZER_GO // Must be included in this file to make sure everything is inlined. -#include "tsan_interface_inl.h" +# include "tsan_interface_inl.h" #endif diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp @@ -129,7 +129,7 @@ // We set thr->suppress_reports in the fork context. // Taking any locking in the fork context can lead to deadlocks. // If any locks are already taken, it's too late to do this check. - CheckNoLocks(thr); + CheckedMutex::CheckNoLocks(); // For the same reason check we didn't lock thread_registry yet. if (SANITIZER_DEBUG) ThreadRegistryLock l(ctx->thread_registry); @@ -596,7 +596,7 @@ } void ReportRace(ThreadState *thr) { - CheckNoLocks(thr); + CheckedMutex::CheckNoLocks(); // Symbolizer makes lots of intercepted calls. If we try to process them, // at best it will cause deadlocks on internal mutexes. diff --git a/compiler-rt/lib/tsan/rtl/tsan_sync.h b/compiler-rt/lib/tsan/rtl/tsan_sync.h --- a/compiler-rt/lib/tsan/rtl/tsan_sync.h +++ b/compiler-rt/lib/tsan/rtl/tsan_sync.h @@ -17,7 +17,6 @@ #include "sanitizer_common/sanitizer_deadlock_detector_interface.h" #include "tsan_defs.h" #include "tsan_clock.h" -#include "tsan_mutex.h" #include "tsan_dense_alloc.h" namespace __tsan { diff --git a/compiler-rt/lib/tsan/rtl/tsan_trace.h b/compiler-rt/lib/tsan/rtl/tsan_trace.h --- a/compiler-rt/lib/tsan/rtl/tsan_trace.h +++ b/compiler-rt/lib/tsan/rtl/tsan_trace.h @@ -13,7 +13,6 @@ #define TSAN_TRACE_H #include "tsan_defs.h" -#include "tsan_mutex.h" #include "tsan_stack_trace.h" #include "tsan_mutexset.h" diff --git a/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt b/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt --- a/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt +++ b/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt @@ -3,7 +3,6 @@ tsan_dense_alloc_test.cpp tsan_flags_test.cpp tsan_mman_test.cpp - tsan_mutex_test.cpp tsan_shadow_test.cpp tsan_stack_test.cpp tsan_sync_test.cpp diff --git a/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cpp b/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cpp deleted file mode 100644 --- a/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//===-- tsan_mutex_test.cpp -----------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_internal_defs.h" -#include "sanitizer_common/sanitizer_atomic.h" -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_mutex.h" -#include "tsan_mutex.h" -#include "gtest/gtest.h" - -namespace __tsan { - -template -class TestData { - public: - explicit TestData(MutexType *mtx) - : mtx_(mtx) { - for (int i = 0; i < kSize; i++) - data_[i] = 0; - } - - void Write() { - Lock l(mtx_); - T v0 = data_[0]; - for (int i = 0; i < kSize; i++) { - CHECK_EQ(data_[i], v0); - data_[i]++; - } - } - - void Read() { - ReadLock l(mtx_); - T v0 = data_[0]; - for (int i = 0; i < kSize; i++) { - CHECK_EQ(data_[i], v0); - } - } - - void Backoff() { - volatile T data[kSize] = {}; - for (int i = 0; i < kSize; i++) { - data[i]++; - CHECK_EQ(data[i], 1); - } - } - - private: - typedef GenericScopedLock Lock; - static const int kSize = 64; - typedef u64 T; - MutexType *mtx_; - char pad_[kCacheLineSize]; - T data_[kSize]; -}; - -const int kThreads = 8; -const int kWriteRate = 1024; -#if SANITIZER_DEBUG -const int kIters = 16*1024; -#else -const int kIters = 64*1024; -#endif - -template -static void *write_mutex_thread(void *param) { - TestData *data = (TestData*)param; - for (int i = 0; i < kIters; i++) { - data->Write(); - data->Backoff(); - } - return 0; -} - -template -static void *read_mutex_thread(void *param) { - TestData *data = (TestData*)param; - for (int i = 0; i < kIters; i++) { - if ((i % kWriteRate) == 0) - data->Write(); - else - data->Read(); - data->Backoff(); - } - return 0; -} - -TEST(Mutex, Write) { - Mutex mtx(MutexTypeAnnotations); - TestData data(&mtx); - pthread_t threads[kThreads]; - for (int i = 0; i < kThreads; i++) - pthread_create(&threads[i], 0, write_mutex_thread, &data); - for (int i = 0; i < kThreads; i++) - pthread_join(threads[i], 0); -} - -TEST(Mutex, ReadWrite) { - Mutex mtx(MutexTypeAnnotations); - TestData data(&mtx); - pthread_t threads[kThreads]; - for (int i = 0; i < kThreads; i++) - pthread_create(&threads[i], 0, read_mutex_thread, &data); - for (int i = 0; i < kThreads; i++) - pthread_join(threads[i], 0); -} - -TEST(Mutex, SpinWrite) { - SpinMutex mtx; - TestData data(&mtx); - pthread_t threads[kThreads]; - for (int i = 0; i < kThreads; i++) - pthread_create(&threads[i], 0, write_mutex_thread, &data); - for (int i = 0; i < kThreads; i++) - pthread_join(threads[i], 0); -} - -} // namespace __tsan