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