Home | History | Annotate | Download | only in rtl
      1 //===-- tsan_mop.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 "tsan_interface.h"
     14 #include "tsan_test_util.h"
     15 #include "gtest/gtest.h"
     16 #include <stddef.h>
     17 #include <stdint.h>
     18 
     19 TEST(ThreadSanitizer, SimpleWrite) {
     20   ScopedThread t;
     21   MemLoc l;
     22   t.Write1(l);
     23 }
     24 
     25 TEST(ThreadSanitizer, SimpleWriteWrite) {
     26   ScopedThread t1, t2;
     27   MemLoc l1, l2;
     28   t1.Write1(l1);
     29   t2.Write1(l2);
     30 }
     31 
     32 TEST(ThreadSanitizer, WriteWriteRace) {
     33   ScopedThread t1, t2;
     34   MemLoc l;
     35   t1.Write1(l);
     36   t2.Write1(l, true);
     37 }
     38 
     39 TEST(ThreadSanitizer, ReadWriteRace) {
     40   ScopedThread t1, t2;
     41   MemLoc l;
     42   t1.Read1(l);
     43   t2.Write1(l, true);
     44 }
     45 
     46 TEST(ThreadSanitizer, WriteReadRace) {
     47   ScopedThread t1, t2;
     48   MemLoc l;
     49   t1.Write1(l);
     50   t2.Read1(l, true);
     51 }
     52 
     53 TEST(ThreadSanitizer, ReadReadNoRace) {
     54   ScopedThread t1, t2;
     55   MemLoc l;
     56   t1.Read1(l);
     57   t2.Read1(l);
     58 }
     59 
     60 TEST(ThreadSanitizer, WriteThenRead) {
     61   MemLoc l;
     62   ScopedThread t1, t2;
     63   t1.Write1(l);
     64   t1.Read1(l);
     65   t2.Read1(l, true);
     66 }
     67 
     68 TEST(ThreadSanitizer, WriteThenLockedRead) {
     69   Mutex m(Mutex::RW);
     70   MainThread t0;
     71   t0.Create(m);
     72   MemLoc l;
     73   {
     74     ScopedThread t1, t2;
     75 
     76     t1.Write8(l);
     77 
     78     t1.Lock(m);
     79     t1.Read8(l);
     80     t1.Unlock(m);
     81 
     82     t2.Read8(l, true);
     83   }
     84   t0.Destroy(m);
     85 }
     86 
     87 TEST(ThreadSanitizer, LockedWriteThenRead) {
     88   Mutex m(Mutex::RW);
     89   MainThread t0;
     90   t0.Create(m);
     91   MemLoc l;
     92   {
     93     ScopedThread t1, t2;
     94 
     95     t1.Lock(m);
     96     t1.Write8(l);
     97     t1.Unlock(m);
     98 
     99     t1.Read8(l);
    100 
    101     t2.Read8(l, true);
    102   }
    103   t0.Destroy(m);
    104 }
    105 
    106 
    107 TEST(ThreadSanitizer, RaceWithOffset) {
    108   ScopedThread t1, t2;
    109   {
    110     MemLoc l;
    111     t1.Access(l.loc(), true, 8, false);
    112     t2.Access((char*)l.loc() + 4, true, 4, true);
    113   }
    114   {
    115     MemLoc l;
    116     t1.Access(l.loc(), true, 8, false);
    117     t2.Access((char*)l.loc() + 7, true, 1, true);
    118   }
    119   {
    120     MemLoc l;
    121     t1.Access((char*)l.loc() + 4, true, 4, false);
    122     t2.Access((char*)l.loc() + 4, true, 2, true);
    123   }
    124   {
    125     MemLoc l;
    126     t1.Access((char*)l.loc() + 4, true, 4, false);
    127     t2.Access((char*)l.loc() + 6, true, 2, true);
    128   }
    129   {
    130     MemLoc l;
    131     t1.Access((char*)l.loc() + 3, true, 2, false);
    132     t2.Access((char*)l.loc() + 4, true, 1, true);
    133   }
    134   {
    135     MemLoc l;
    136     t1.Access((char*)l.loc() + 1, true, 8, false);
    137     t2.Access((char*)l.loc() + 3, true, 1, true);
    138   }
    139 }
    140 
    141 TEST(ThreadSanitizer, RaceWithOffset2) {
    142   ScopedThread t1, t2;
    143   {
    144     MemLoc l;
    145     t1.Access((char*)l.loc(), true, 4, false);
    146     t2.Access((char*)l.loc() + 2, true, 1, true);
    147   }
    148   {
    149     MemLoc l;
    150     t1.Access((char*)l.loc() + 2, true, 1, false);
    151     t2.Access((char*)l.loc(), true, 4, true);
    152   }
    153 }
    154 
    155 TEST(ThreadSanitizer, NoRaceWithOffset) {
    156   ScopedThread t1, t2;
    157   {
    158     MemLoc l;
    159     t1.Access(l.loc(), true, 4, false);
    160     t2.Access((char*)l.loc() + 4, true, 4, false);
    161   }
    162   {
    163     MemLoc l;
    164     t1.Access((char*)l.loc() + 3, true, 2, false);
    165     t2.Access((char*)l.loc() + 1, true, 2, false);
    166     t2.Access((char*)l.loc() + 5, true, 2, false);
    167   }
    168 }
    169 
    170 TEST(ThreadSanitizer, RaceWithDeadThread) {
    171   MemLoc l;
    172   ScopedThread t;
    173   ScopedThread().Write1(l);
    174   t.Write1(l, true);
    175 }
    176 
    177 TEST(ThreadSanitizer, BenignRaceOnVptr) {
    178   void *vptr_storage;
    179   MemLoc vptr(&vptr_storage), val;
    180   vptr_storage = val.loc();
    181   ScopedThread t1, t2;
    182   t1.VptrUpdate(vptr, val);
    183   t2.Read8(vptr);
    184 }
    185 
    186 TEST(ThreadSanitizer, HarmfulRaceOnVptr) {
    187   void *vptr_storage;
    188   MemLoc vptr(&vptr_storage), val1, val2;
    189   vptr_storage = val1.loc();
    190   ScopedThread t1, t2;
    191   t1.VptrUpdate(vptr, val2);
    192   t2.Read8(vptr, true);
    193 }
    194 
    195 static void foo() {
    196   volatile int x = 42;
    197   int x2 = x;
    198   (void)x2;
    199 }
    200 
    201 static void bar() {
    202   volatile int x = 43;
    203   int x2 = x;
    204   (void)x2;
    205 }
    206 
    207 TEST(ThreadSanitizer, ReportDeadThread) {
    208   MemLoc l;
    209   ScopedThread t1;
    210   {
    211     ScopedThread t2;
    212     t2.Call(&foo);
    213     t2.Call(&bar);
    214     t2.Write1(l);
    215   }
    216   t1.Write1(l, true);
    217 }
    218 
    219 struct ClassWithStatic {
    220   static int Data[4];
    221 };
    222 
    223 int ClassWithStatic::Data[4];
    224 
    225 static void foobarbaz() {}
    226 
    227 TEST(ThreadSanitizer, ReportRace) {
    228   ScopedThread t1;
    229   MainThread().Access(&ClassWithStatic::Data, true, 4, false);
    230   t1.Call(&foobarbaz);
    231   t1.Access(&ClassWithStatic::Data, true, 2, true);
    232   t1.Return();
    233 }
    234