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 8uint64_t objs[8*2*(2 + 4 + 8)][2]; 9 10extern "C" { 11uint16_t __sanitizer_unaligned_load16(void *addr); 12uint32_t __sanitizer_unaligned_load32(void *addr); 13uint64_t __sanitizer_unaligned_load64(void *addr); 14void __sanitizer_unaligned_store16(void *addr, uint16_t v); 15void __sanitizer_unaligned_store32(void *addr, uint32_t v); 16void __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 22static 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 40static 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 49template<int off, int off2> 50static 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 65template<int off> 66static 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 85static 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 104void 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 120void *Thread(void *p) { 121 (void)p; 122 sleep(1); 123 Test(false); 124 return 0; 125} 126 127int 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