13cab2bb3Spatrick //===-- tsan_mutex.cpp ----------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
123cab2bb3Spatrick #include "sanitizer_common/sanitizer_atomic.h"
133cab2bb3Spatrick #include "tsan_interface.h"
143cab2bb3Spatrick #include "tsan_interface_ann.h"
153cab2bb3Spatrick #include "tsan_test_util.h"
163cab2bb3Spatrick #include "gtest/gtest.h"
173cab2bb3Spatrick #include <stdint.h>
183cab2bb3Spatrick
193cab2bb3Spatrick namespace __tsan {
203cab2bb3Spatrick
TEST_F(ThreadSanitizer,BasicMutex)21*810390e3Srobert TEST_F(ThreadSanitizer, BasicMutex) {
223cab2bb3Spatrick ScopedThread t;
23d89ec533Spatrick UserMutex m;
243cab2bb3Spatrick t.Create(m);
253cab2bb3Spatrick
263cab2bb3Spatrick t.Lock(m);
273cab2bb3Spatrick t.Unlock(m);
283cab2bb3Spatrick
293cab2bb3Spatrick CHECK(t.TryLock(m));
303cab2bb3Spatrick t.Unlock(m);
313cab2bb3Spatrick
323cab2bb3Spatrick t.Lock(m);
333cab2bb3Spatrick CHECK(!t.TryLock(m));
343cab2bb3Spatrick t.Unlock(m);
353cab2bb3Spatrick
363cab2bb3Spatrick t.Destroy(m);
373cab2bb3Spatrick }
383cab2bb3Spatrick
TEST_F(ThreadSanitizer,BasicSpinMutex)39*810390e3Srobert TEST_F(ThreadSanitizer, BasicSpinMutex) {
403cab2bb3Spatrick ScopedThread t;
41d89ec533Spatrick UserMutex m(UserMutex::Spin);
423cab2bb3Spatrick t.Create(m);
433cab2bb3Spatrick
443cab2bb3Spatrick t.Lock(m);
453cab2bb3Spatrick t.Unlock(m);
463cab2bb3Spatrick
473cab2bb3Spatrick CHECK(t.TryLock(m));
483cab2bb3Spatrick t.Unlock(m);
493cab2bb3Spatrick
503cab2bb3Spatrick t.Lock(m);
513cab2bb3Spatrick CHECK(!t.TryLock(m));
523cab2bb3Spatrick t.Unlock(m);
533cab2bb3Spatrick
543cab2bb3Spatrick t.Destroy(m);
553cab2bb3Spatrick }
563cab2bb3Spatrick
TEST_F(ThreadSanitizer,BasicRwMutex)57*810390e3Srobert TEST_F(ThreadSanitizer, BasicRwMutex) {
583cab2bb3Spatrick ScopedThread t;
59d89ec533Spatrick UserMutex m(UserMutex::RW);
603cab2bb3Spatrick t.Create(m);
613cab2bb3Spatrick
623cab2bb3Spatrick t.Lock(m);
633cab2bb3Spatrick t.Unlock(m);
643cab2bb3Spatrick
653cab2bb3Spatrick CHECK(t.TryLock(m));
663cab2bb3Spatrick t.Unlock(m);
673cab2bb3Spatrick
683cab2bb3Spatrick t.Lock(m);
693cab2bb3Spatrick CHECK(!t.TryLock(m));
703cab2bb3Spatrick t.Unlock(m);
713cab2bb3Spatrick
723cab2bb3Spatrick t.ReadLock(m);
733cab2bb3Spatrick t.ReadUnlock(m);
743cab2bb3Spatrick
753cab2bb3Spatrick CHECK(t.TryReadLock(m));
763cab2bb3Spatrick t.ReadUnlock(m);
773cab2bb3Spatrick
783cab2bb3Spatrick t.Lock(m);
793cab2bb3Spatrick CHECK(!t.TryReadLock(m));
803cab2bb3Spatrick t.Unlock(m);
813cab2bb3Spatrick
823cab2bb3Spatrick t.ReadLock(m);
833cab2bb3Spatrick CHECK(!t.TryLock(m));
843cab2bb3Spatrick t.ReadUnlock(m);
853cab2bb3Spatrick
863cab2bb3Spatrick t.ReadLock(m);
873cab2bb3Spatrick CHECK(t.TryReadLock(m));
883cab2bb3Spatrick t.ReadUnlock(m);
893cab2bb3Spatrick t.ReadUnlock(m);
903cab2bb3Spatrick
913cab2bb3Spatrick t.Destroy(m);
923cab2bb3Spatrick }
933cab2bb3Spatrick
TEST_F(ThreadSanitizer,Mutex)94*810390e3Srobert TEST_F(ThreadSanitizer, Mutex) {
95d89ec533Spatrick UserMutex m;
963cab2bb3Spatrick MainThread t0;
973cab2bb3Spatrick t0.Create(m);
983cab2bb3Spatrick
993cab2bb3Spatrick ScopedThread t1, t2;
1003cab2bb3Spatrick MemLoc l;
1013cab2bb3Spatrick t1.Lock(m);
1023cab2bb3Spatrick t1.Write1(l);
1033cab2bb3Spatrick t1.Unlock(m);
1043cab2bb3Spatrick t2.Lock(m);
1053cab2bb3Spatrick t2.Write1(l);
1063cab2bb3Spatrick t2.Unlock(m);
1073cab2bb3Spatrick t2.Destroy(m);
1083cab2bb3Spatrick }
1093cab2bb3Spatrick
TEST_F(ThreadSanitizer,SpinMutex)110*810390e3Srobert TEST_F(ThreadSanitizer, SpinMutex) {
111d89ec533Spatrick UserMutex m(UserMutex::Spin);
1123cab2bb3Spatrick MainThread t0;
1133cab2bb3Spatrick t0.Create(m);
1143cab2bb3Spatrick
1153cab2bb3Spatrick ScopedThread t1, t2;
1163cab2bb3Spatrick MemLoc l;
1173cab2bb3Spatrick t1.Lock(m);
1183cab2bb3Spatrick t1.Write1(l);
1193cab2bb3Spatrick t1.Unlock(m);
1203cab2bb3Spatrick t2.Lock(m);
1213cab2bb3Spatrick t2.Write1(l);
1223cab2bb3Spatrick t2.Unlock(m);
1233cab2bb3Spatrick t2.Destroy(m);
1243cab2bb3Spatrick }
1253cab2bb3Spatrick
TEST_F(ThreadSanitizer,RwMutex)126*810390e3Srobert TEST_F(ThreadSanitizer, RwMutex) {
127d89ec533Spatrick UserMutex m(UserMutex::RW);
1283cab2bb3Spatrick MainThread t0;
1293cab2bb3Spatrick t0.Create(m);
1303cab2bb3Spatrick
1313cab2bb3Spatrick ScopedThread t1, t2, t3;
1323cab2bb3Spatrick MemLoc l;
1333cab2bb3Spatrick t1.Lock(m);
1343cab2bb3Spatrick t1.Write1(l);
1353cab2bb3Spatrick t1.Unlock(m);
1363cab2bb3Spatrick t2.Lock(m);
1373cab2bb3Spatrick t2.Write1(l);
1383cab2bb3Spatrick t2.Unlock(m);
1393cab2bb3Spatrick t1.ReadLock(m);
1403cab2bb3Spatrick t3.ReadLock(m);
1413cab2bb3Spatrick t1.Read1(l);
1423cab2bb3Spatrick t3.Read1(l);
1433cab2bb3Spatrick t1.ReadUnlock(m);
1443cab2bb3Spatrick t3.ReadUnlock(m);
1453cab2bb3Spatrick t2.Lock(m);
1463cab2bb3Spatrick t2.Write1(l);
1473cab2bb3Spatrick t2.Unlock(m);
1483cab2bb3Spatrick t2.Destroy(m);
1493cab2bb3Spatrick }
1503cab2bb3Spatrick
TEST_F(ThreadSanitizer,StaticMutex)151*810390e3Srobert TEST_F(ThreadSanitizer, StaticMutex) {
1523cab2bb3Spatrick // Emulates statically initialized mutex.
153d89ec533Spatrick UserMutex m;
1543cab2bb3Spatrick m.StaticInit();
1553cab2bb3Spatrick {
1563cab2bb3Spatrick ScopedThread t1, t2;
1573cab2bb3Spatrick t1.Lock(m);
1583cab2bb3Spatrick t1.Unlock(m);
1593cab2bb3Spatrick t2.Lock(m);
1603cab2bb3Spatrick t2.Unlock(m);
1613cab2bb3Spatrick }
1623cab2bb3Spatrick MainThread().Destroy(m);
1633cab2bb3Spatrick }
1643cab2bb3Spatrick
singleton_thread(void * param)1653cab2bb3Spatrick static void *singleton_thread(void *param) {
1663cab2bb3Spatrick atomic_uintptr_t *singleton = (atomic_uintptr_t *)param;
1673cab2bb3Spatrick for (int i = 0; i < 4*1024*1024; i++) {
1683cab2bb3Spatrick int *val = (int *)atomic_load(singleton, memory_order_acquire);
1693cab2bb3Spatrick __tsan_acquire(singleton);
1703cab2bb3Spatrick __tsan_read4(val);
1713cab2bb3Spatrick CHECK_EQ(*val, 42);
1723cab2bb3Spatrick }
1733cab2bb3Spatrick return 0;
1743cab2bb3Spatrick }
1753cab2bb3Spatrick
TEST(DISABLED_BENCH_ThreadSanitizer,Singleton)1763cab2bb3Spatrick TEST(DISABLED_BENCH_ThreadSanitizer, Singleton) {
1773cab2bb3Spatrick const int kClockSize = 100;
1783cab2bb3Spatrick const int kThreadCount = 8;
1793cab2bb3Spatrick
1803cab2bb3Spatrick // Puff off thread's clock.
1813cab2bb3Spatrick for (int i = 0; i < kClockSize; i++) {
1823cab2bb3Spatrick ScopedThread t1;
1833cab2bb3Spatrick (void)t1;
1843cab2bb3Spatrick }
1853cab2bb3Spatrick // Create the singleton.
1863cab2bb3Spatrick int val = 42;
1873cab2bb3Spatrick __tsan_write4(&val);
1883cab2bb3Spatrick atomic_uintptr_t singleton;
1893cab2bb3Spatrick __tsan_release(&singleton);
1903cab2bb3Spatrick atomic_store(&singleton, (uintptr_t)&val, memory_order_release);
1913cab2bb3Spatrick // Create reader threads.
1923cab2bb3Spatrick pthread_t threads[kThreadCount];
1933cab2bb3Spatrick for (int t = 0; t < kThreadCount; t++)
1943cab2bb3Spatrick pthread_create(&threads[t], 0, singleton_thread, &singleton);
1953cab2bb3Spatrick for (int t = 0; t < kThreadCount; t++)
1963cab2bb3Spatrick pthread_join(threads[t], 0);
1973cab2bb3Spatrick }
1983cab2bb3Spatrick
TEST(DISABLED_BENCH_ThreadSanitizer,StopFlag)1993cab2bb3Spatrick TEST(DISABLED_BENCH_ThreadSanitizer, StopFlag) {
2003cab2bb3Spatrick const int kClockSize = 100;
2013cab2bb3Spatrick const int kIters = 16*1024*1024;
2023cab2bb3Spatrick
2033cab2bb3Spatrick // Puff off thread's clock.
2043cab2bb3Spatrick for (int i = 0; i < kClockSize; i++) {
2053cab2bb3Spatrick ScopedThread t1;
2063cab2bb3Spatrick (void)t1;
2073cab2bb3Spatrick }
2083cab2bb3Spatrick // Create the stop flag.
2093cab2bb3Spatrick atomic_uintptr_t flag;
2103cab2bb3Spatrick __tsan_release(&flag);
2113cab2bb3Spatrick atomic_store(&flag, 0, memory_order_release);
2123cab2bb3Spatrick // Read it a lot.
2133cab2bb3Spatrick for (int i = 0; i < kIters; i++) {
2143cab2bb3Spatrick uptr v = atomic_load(&flag, memory_order_acquire);
2153cab2bb3Spatrick __tsan_acquire(&flag);
2163cab2bb3Spatrick CHECK_EQ(v, 0);
2173cab2bb3Spatrick }
2183cab2bb3Spatrick }
2193cab2bb3Spatrick
2203cab2bb3Spatrick } // namespace __tsan
221