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