Home | History | Annotate | Download | only in lit_tests
      1 // RUN: %clangxx_tsan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
      2 #include <pthread.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <stdint.h>
      6 #include <unistd.h>
      7 
      8 uint64_t objs[8*2*(2 + 4 + 8)][2];
      9 
     10 extern "C" {
     11 uint16_t __sanitizer_unaligned_load16(void *addr);
     12 uint32_t __sanitizer_unaligned_load32(void *addr);
     13 uint64_t __sanitizer_unaligned_load64(void *addr);
     14 void __sanitizer_unaligned_store16(void *addr, uint16_t v);
     15 void __sanitizer_unaligned_store32(void *addr, uint32_t v);
     16 void __sanitizer_unaligned_store64(void *addr, uint64_t v);
     17 }
     18 
     19 // All this mess is to generate unique stack for each race,
     20 // otherwise tsan will suppress similar stacks.
     21 
     22 static void access(char *p, int sz, int rw) {
     23   if (rw) {
     24     switch (sz) {
     25     case 0: __sanitizer_unaligned_store16(p, 0); break;
     26     case 1: __sanitizer_unaligned_store32(p, 0); break;
     27     case 2: __sanitizer_unaligned_store64(p, 0); break;
     28     default: exit(1);
     29     }
     30   } else {
     31     switch (sz) {
     32     case 0: __sanitizer_unaligned_load16(p); break;
     33     case 1: __sanitizer_unaligned_load32(p); break;
     34     case 2: __sanitizer_unaligned_load64(p); break;
     35     default: exit(1);
     36     }
     37   }
     38 }
     39 
     40 static int accesssize(int sz) {
     41   switch (sz) {
     42   case 0: return 2;
     43   case 1: return 4;
     44   case 2: return 8;
     45   }
     46   exit(1);
     47 }
     48 
     49 template<int off, int off2>
     50 static void access3(bool main, int sz1, bool rw, char *p) {
     51   p += off;
     52   if (main) {
     53     access(p, sz1, true);
     54   } else {
     55     p += off2;
     56     if (rw) {
     57       *p = 42;
     58     } else {
     59        if (*p == 42)
     60          printf("bingo!\n");
     61     }
     62   }
     63 }
     64 
     65 template<int off>
     66 static void access2(bool main, int sz1, int off2, bool rw, char *obj) {
     67   if (off2 == 0)
     68     access3<off, 0>(main, sz1, rw, obj);
     69   else if (off2 == 1)
     70     access3<off, 1>(main, sz1, rw, obj);
     71   else if (off2 == 2)
     72     access3<off, 2>(main, sz1, rw, obj);
     73   else if (off2 == 3)
     74     access3<off, 3>(main, sz1, rw, obj);
     75   else if (off2 == 4)
     76     access3<off, 4>(main, sz1, rw, obj);
     77   else if (off2 == 5)
     78     access3<off, 5>(main, sz1, rw, obj);
     79   else if (off2 == 6)
     80     access3<off, 6>(main, sz1, rw, obj);
     81   else if (off2 == 7)
     82     access3<off, 7>(main, sz1, rw, obj);
     83 }
     84 
     85 static void access1(bool main, int off, int sz1, int off2, bool rw, char *obj) {
     86   if (off == 0)
     87     access2<0>(main, sz1, off2, rw, obj);
     88   else if (off == 1)
     89     access2<1>(main, sz1, off2, rw, obj);
     90   else if (off == 2)
     91     access2<2>(main, sz1, off2, rw, obj);
     92   else if (off == 3)
     93     access2<3>(main, sz1, off2, rw, obj);
     94   else if (off == 4)
     95     access2<4>(main, sz1, off2, rw, obj);
     96   else if (off == 5)
     97     access2<5>(main, sz1, off2, rw, obj);
     98   else if (off == 6)
     99     access2<6>(main, sz1, off2, rw, obj);
    100   else if (off == 7)
    101     access2<7>(main, sz1, off2, rw, obj);
    102 }
    103 
    104 void Test(bool main) {
    105   uint64_t *obj = objs[0];
    106   for (int off = 0; off < 8; off++) {
    107     for (int sz1 = 0; sz1 < 3; sz1++) {
    108       for (int off2 = 0; off2 < accesssize(sz1); off2++) {
    109         for (int rw = 0; rw < 2; rw++) {
    110           // printf("thr=%d off=%d sz1=%d off2=%d rw=%d p=%p\n",
    111           //        main, off, sz1, off2, rw, obj);
    112           access1(main, off, sz1, off2, rw, (char*)obj);
    113           obj += 2;
    114         }
    115       }
    116     }
    117   }
    118 }
    119 
    120 void *Thread(void *p) {
    121   (void)p;
    122   sleep(1);
    123   Test(false);
    124   return 0;
    125 }
    126 
    127 int main() {
    128   pthread_t th;
    129   pthread_create(&th, 0, Thread, 0);
    130   Test(true);
    131   pthread_join(th, 0);
    132 }
    133 
    134 // CHECK: WARNING: ThreadSanitizer: data race
    135 // CHECK: ThreadSanitizer: reported 224 warnings
    136