brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.3 KiB · d45014b Raw
221 lines · cpp
1//===-- tsan_mutex.cpp ----------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of ThreadSanitizer (TSan), a race detector.10//11//===----------------------------------------------------------------------===//12#include "sanitizer_common/sanitizer_atomic.h"13#include "tsan_interface.h"14#include "tsan_interface_ann.h"15#include "tsan_test_util.h"16#include "gtest/gtest.h"17#include <stdint.h>18 19namespace __tsan {20 21TEST_F(ThreadSanitizer, BasicMutex) {22  ScopedThread t;23  UserMutex m;24  t.Create(m);25 26  t.Lock(m);27  t.Unlock(m);28 29  CHECK(t.TryLock(m));30  t.Unlock(m);31 32  t.Lock(m);33  CHECK(!t.TryLock(m));34  t.Unlock(m);35 36  t.Destroy(m);37}38 39TEST_F(ThreadSanitizer, BasicSpinMutex) {40  ScopedThread t;41  UserMutex m(UserMutex::Spin);42  t.Create(m);43 44  t.Lock(m);45  t.Unlock(m);46 47  CHECK(t.TryLock(m));48  t.Unlock(m);49 50  t.Lock(m);51  CHECK(!t.TryLock(m));52  t.Unlock(m);53 54  t.Destroy(m);55}56 57TEST_F(ThreadSanitizer, BasicRwMutex) {58  ScopedThread t;59  UserMutex m(UserMutex::RW);60  t.Create(m);61 62  t.Lock(m);63  t.Unlock(m);64 65  CHECK(t.TryLock(m));66  t.Unlock(m);67 68  t.Lock(m);69  CHECK(!t.TryLock(m));70  t.Unlock(m);71 72  t.ReadLock(m);73  t.ReadUnlock(m);74 75  CHECK(t.TryReadLock(m));76  t.ReadUnlock(m);77 78  t.Lock(m);79  CHECK(!t.TryReadLock(m));80  t.Unlock(m);81 82  t.ReadLock(m);83  CHECK(!t.TryLock(m));84  t.ReadUnlock(m);85 86  t.ReadLock(m);87  CHECK(t.TryReadLock(m));88  t.ReadUnlock(m);89  t.ReadUnlock(m);90 91  t.Destroy(m);92}93 94TEST_F(ThreadSanitizer, Mutex) {95  UserMutex m;96  MainThread t0;97  t0.Create(m);98 99  ScopedThread t1, t2;100  MemLoc l;101  t1.Lock(m);102  t1.Write1(l);103  t1.Unlock(m);104  t2.Lock(m);105  t2.Write1(l);106  t2.Unlock(m);107  t2.Destroy(m);108}109 110TEST_F(ThreadSanitizer, SpinMutex) {111  UserMutex m(UserMutex::Spin);112  MainThread t0;113  t0.Create(m);114 115  ScopedThread t1, t2;116  MemLoc l;117  t1.Lock(m);118  t1.Write1(l);119  t1.Unlock(m);120  t2.Lock(m);121  t2.Write1(l);122  t2.Unlock(m);123  t2.Destroy(m);124}125 126TEST_F(ThreadSanitizer, RwMutex) {127  UserMutex m(UserMutex::RW);128  MainThread t0;129  t0.Create(m);130 131  ScopedThread t1, t2, t3;132  MemLoc l;133  t1.Lock(m);134  t1.Write1(l);135  t1.Unlock(m);136  t2.Lock(m);137  t2.Write1(l);138  t2.Unlock(m);139  t1.ReadLock(m);140  t3.ReadLock(m);141  t1.Read1(l);142  t3.Read1(l);143  t1.ReadUnlock(m);144  t3.ReadUnlock(m);145  t2.Lock(m);146  t2.Write1(l);147  t2.Unlock(m);148  t2.Destroy(m);149}150 151TEST_F(ThreadSanitizer, StaticMutex) {152  // Emulates statically initialized mutex.153  UserMutex m;154  m.StaticInit();155  {156    ScopedThread t1, t2;157    t1.Lock(m);158    t1.Unlock(m);159    t2.Lock(m);160    t2.Unlock(m);161  }162  MainThread().Destroy(m);163}164 165static void *singleton_thread(void *param) {166  atomic_uintptr_t *singleton = (atomic_uintptr_t *)param;167  for (int i = 0; i < 4*1024*1024; i++) {168    int *val = (int *)atomic_load(singleton, memory_order_acquire);169    __tsan_acquire(singleton);170    __tsan_read4(val);171    CHECK_EQ(*val, 42);172  }173  return 0;174}175 176TEST(DISABLED_BENCH_ThreadSanitizer, Singleton) {177  const int kClockSize = 100;178  const int kThreadCount = 8;179 180  // Puff off thread's clock.181  for (int i = 0; i < kClockSize; i++) {182    ScopedThread t1;183    (void)t1;184  }185  // Create the singleton.186  int val = 42;187  __tsan_write4(&val);188  atomic_uintptr_t singleton;189  __tsan_release(&singleton);190  atomic_store(&singleton, (uintptr_t)&val, memory_order_release);191  // Create reader threads.192  pthread_t threads[kThreadCount];193  for (int t = 0; t < kThreadCount; t++)194    pthread_create(&threads[t], 0, singleton_thread, &singleton);195  for (int t = 0; t < kThreadCount; t++)196    pthread_join(threads[t], 0);197}198 199TEST(DISABLED_BENCH_ThreadSanitizer, StopFlag) {200  const int kClockSize = 100;201  const int kIters = 16*1024*1024;202 203  // Puff off thread's clock.204  for (int i = 0; i < kClockSize; i++) {205    ScopedThread t1;206    (void)t1;207  }208  // Create the stop flag.209  atomic_uintptr_t flag;210  __tsan_release(&flag);211  atomic_store(&flag, 0, memory_order_release);212  // Read it a lot.213  for (int i = 0; i < kIters; i++) {214    uptr v = atomic_load(&flag, memory_order_acquire);215    __tsan_acquire(&flag);216    CHECK_EQ(v, 0);217  }218}219 220}  // namespace __tsan221