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