aboutsummaryrefslogtreecommitdiff
path: root/lib/tsan/tests/rtl/tsan_mutex.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tsan/tests/rtl/tsan_mutex.cc')
-rw-r--r--lib/tsan/tests/rtl/tsan_mutex.cc221
1 files changed, 221 insertions, 0 deletions
diff --git a/lib/tsan/tests/rtl/tsan_mutex.cc b/lib/tsan/tests/rtl/tsan_mutex.cc
new file mode 100644
index 000000000000..4d9c77961818
--- /dev/null
+++ b/lib/tsan/tests/rtl/tsan_mutex.cc
@@ -0,0 +1,221 @@
+//===-- tsan_mutex.cc -----------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "tsan_interface.h"
+#include "tsan_interface_ann.h"
+#include "tsan_test_util.h"
+#include "gtest/gtest.h"
+#include <stdint.h>
+
+namespace __tsan {
+
+TEST(ThreadSanitizer, BasicMutex) {
+ ScopedThread t;
+ Mutex m;
+ t.Create(m);
+
+ t.Lock(m);
+ t.Unlock(m);
+
+ CHECK(t.TryLock(m));
+ t.Unlock(m);
+
+ t.Lock(m);
+ CHECK(!t.TryLock(m));
+ t.Unlock(m);
+
+ t.Destroy(m);
+}
+
+TEST(ThreadSanitizer, BasicSpinMutex) {
+ ScopedThread t;
+ Mutex m(Mutex::Spin);
+ t.Create(m);
+
+ t.Lock(m);
+ t.Unlock(m);
+
+ CHECK(t.TryLock(m));
+ t.Unlock(m);
+
+ t.Lock(m);
+ CHECK(!t.TryLock(m));
+ t.Unlock(m);
+
+ t.Destroy(m);
+}
+
+TEST(ThreadSanitizer, BasicRwMutex) {
+ ScopedThread t;
+ Mutex m(Mutex::RW);
+ t.Create(m);
+
+ t.Lock(m);
+ t.Unlock(m);
+
+ CHECK(t.TryLock(m));
+ t.Unlock(m);
+
+ t.Lock(m);
+ CHECK(!t.TryLock(m));
+ t.Unlock(m);
+
+ t.ReadLock(m);
+ t.ReadUnlock(m);
+
+ CHECK(t.TryReadLock(m));
+ t.ReadUnlock(m);
+
+ t.Lock(m);
+ CHECK(!t.TryReadLock(m));
+ t.Unlock(m);
+
+ t.ReadLock(m);
+ CHECK(!t.TryLock(m));
+ t.ReadUnlock(m);
+
+ t.ReadLock(m);
+ CHECK(t.TryReadLock(m));
+ t.ReadUnlock(m);
+ t.ReadUnlock(m);
+
+ t.Destroy(m);
+}
+
+TEST(ThreadSanitizer, Mutex) {
+ Mutex m;
+ MainThread t0;
+ t0.Create(m);
+
+ ScopedThread t1, t2;
+ MemLoc l;
+ t1.Lock(m);
+ t1.Write1(l);
+ t1.Unlock(m);
+ t2.Lock(m);
+ t2.Write1(l);
+ t2.Unlock(m);
+ t2.Destroy(m);
+}
+
+TEST(ThreadSanitizer, SpinMutex) {
+ Mutex m(Mutex::Spin);
+ MainThread t0;
+ t0.Create(m);
+
+ ScopedThread t1, t2;
+ MemLoc l;
+ t1.Lock(m);
+ t1.Write1(l);
+ t1.Unlock(m);
+ t2.Lock(m);
+ t2.Write1(l);
+ t2.Unlock(m);
+ t2.Destroy(m);
+}
+
+TEST(ThreadSanitizer, RwMutex) {
+ Mutex m(Mutex::RW);
+ MainThread t0;
+ t0.Create(m);
+
+ ScopedThread t1, t2, t3;
+ MemLoc l;
+ t1.Lock(m);
+ t1.Write1(l);
+ t1.Unlock(m);
+ t2.Lock(m);
+ t2.Write1(l);
+ t2.Unlock(m);
+ t1.ReadLock(m);
+ t3.ReadLock(m);
+ t1.Read1(l);
+ t3.Read1(l);
+ t1.ReadUnlock(m);
+ t3.ReadUnlock(m);
+ t2.Lock(m);
+ t2.Write1(l);
+ t2.Unlock(m);
+ t2.Destroy(m);
+}
+
+TEST(ThreadSanitizer, StaticMutex) {
+ // Emulates statically initialized mutex.
+ Mutex m;
+ m.StaticInit();
+ {
+ ScopedThread t1, t2;
+ t1.Lock(m);
+ t1.Unlock(m);
+ t2.Lock(m);
+ t2.Unlock(m);
+ }
+ MainThread().Destroy(m);
+}
+
+static void *singleton_thread(void *param) {
+ atomic_uintptr_t *singleton = (atomic_uintptr_t *)param;
+ for (int i = 0; i < 4*1024*1024; i++) {
+ int *val = (int *)atomic_load(singleton, memory_order_acquire);
+ __tsan_acquire(singleton);
+ __tsan_read4(val);
+ CHECK_EQ(*val, 42);
+ }
+ return 0;
+}
+
+TEST(DISABLED_BENCH_ThreadSanitizer, Singleton) {
+ const int kClockSize = 100;
+ const int kThreadCount = 8;
+
+ // Puff off thread's clock.
+ for (int i = 0; i < kClockSize; i++) {
+ ScopedThread t1;
+ (void)t1;
+ }
+ // Create the singleton.
+ int val = 42;
+ __tsan_write4(&val);
+ atomic_uintptr_t singleton;
+ __tsan_release(&singleton);
+ atomic_store(&singleton, (uintptr_t)&val, memory_order_release);
+ // Create reader threads.
+ pthread_t threads[kThreadCount];
+ for (int t = 0; t < kThreadCount; t++)
+ pthread_create(&threads[t], 0, singleton_thread, &singleton);
+ for (int t = 0; t < kThreadCount; t++)
+ pthread_join(threads[t], 0);
+}
+
+TEST(DISABLED_BENCH_ThreadSanitizer, StopFlag) {
+ const int kClockSize = 100;
+ const int kIters = 16*1024*1024;
+
+ // Puff off thread's clock.
+ for (int i = 0; i < kClockSize; i++) {
+ ScopedThread t1;
+ (void)t1;
+ }
+ // Create the stop flag.
+ atomic_uintptr_t flag;
+ __tsan_release(&flag);
+ atomic_store(&flag, 0, memory_order_release);
+ // Read it a lot.
+ for (int i = 0; i < kIters; i++) {
+ uptr v = atomic_load(&flag, memory_order_acquire);
+ __tsan_acquire(&flag);
+ CHECK_EQ(v, 0);
+ }
+}
+
+} // namespace __tsan