15d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s 28ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov#include <pthread.h> 38ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov#include <stdio.h> 48ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov#include <stdlib.h> 58ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov#include <stdint.h> 68ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov#include <unistd.h> 78ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 82d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define NOINLINE __attribute__((noinline)) 92d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvolatile uint64_t objs[8*2*(2 + 4 + 8)][2]; 118ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 128ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukovextern "C" { 132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuint16_t __sanitizer_unaligned_load16(volatile void *addr); 142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuint32_t __sanitizer_unaligned_load32(volatile void *addr); 152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuint64_t __sanitizer_unaligned_load64(volatile void *addr); 162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid __sanitizer_unaligned_store16(volatile void *addr, uint16_t v); 172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid __sanitizer_unaligned_store32(volatile void *addr, uint32_t v); 182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid __sanitizer_unaligned_store64(volatile void *addr, uint64_t v); 198ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov} 208ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 218ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov// All this mess is to generate unique stack for each race, 228ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov// otherwise tsan will suppress similar stacks. 238ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic NOINLINE void access(volatile char *p, int sz, int rw) { 258ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov if (rw) { 268ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov switch (sz) { 278ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov case 0: __sanitizer_unaligned_store16(p, 0); break; 288ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov case 1: __sanitizer_unaligned_store32(p, 0); break; 298ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov case 2: __sanitizer_unaligned_store64(p, 0); break; 308ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov default: exit(1); 318ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 328ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } else { 338ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov switch (sz) { 348ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov case 0: __sanitizer_unaligned_load16(p); break; 358ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov case 1: __sanitizer_unaligned_load32(p); break; 368ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov case 2: __sanitizer_unaligned_load64(p); break; 378ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov default: exit(1); 388ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 398ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 408ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov} 418ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 428ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukovstatic int accesssize(int sz) { 438ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov switch (sz) { 448ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov case 0: return 2; 458ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov case 1: return 4; 468ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov case 2: return 8; 478ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 488ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov exit(1); 498ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov} 508ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 518ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukovtemplate<int off, int off2> 522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic NOINLINE void access3(bool main, int sz1, bool rw, volatile char *p) { 538ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov p += off; 548ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov if (main) { 558ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access(p, sz1, true); 568ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } else { 578ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov p += off2; 588ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov if (rw) { 598ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov *p = 42; 608ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } else { 618ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov if (*p == 42) 628ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov printf("bingo!\n"); 638ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 648ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 658ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov} 668ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 678ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukovtemplate<int off> 682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic NOINLINE void 692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesaccess2(bool main, int sz1, int off2, bool rw, volatile char *obj) { 708ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov if (off2 == 0) 718ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access3<off, 0>(main, sz1, rw, obj); 728ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off2 == 1) 738ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access3<off, 1>(main, sz1, rw, obj); 748ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off2 == 2) 758ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access3<off, 2>(main, sz1, rw, obj); 768ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off2 == 3) 778ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access3<off, 3>(main, sz1, rw, obj); 788ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off2 == 4) 798ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access3<off, 4>(main, sz1, rw, obj); 808ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off2 == 5) 818ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access3<off, 5>(main, sz1, rw, obj); 828ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off2 == 6) 838ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access3<off, 6>(main, sz1, rw, obj); 848ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off2 == 7) 858ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access3<off, 7>(main, sz1, rw, obj); 868ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov} 878ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic NOINLINE void 892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesaccess1(bool main, int off, int sz1, int off2, bool rw, char *obj) { 908ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov if (off == 0) 918ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access2<0>(main, sz1, off2, rw, obj); 928ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off == 1) 938ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access2<1>(main, sz1, off2, rw, obj); 948ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off == 2) 958ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access2<2>(main, sz1, off2, rw, obj); 968ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off == 3) 978ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access2<3>(main, sz1, off2, rw, obj); 988ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off == 4) 998ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access2<4>(main, sz1, off2, rw, obj); 1008ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off == 5) 1018ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access2<5>(main, sz1, off2, rw, obj); 1028ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off == 6) 1038ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access2<6>(main, sz1, off2, rw, obj); 1048ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov else if (off == 7) 1058ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access2<7>(main, sz1, off2, rw, obj); 1068ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov} 1078ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesNOINLINE void Test(bool main) { 1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines volatile uint64_t *obj = objs[0]; 1108ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov for (int off = 0; off < 8; off++) { 1118ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov for (int sz1 = 0; sz1 < 3; sz1++) { 1128ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov for (int off2 = 0; off2 < accesssize(sz1); off2++) { 1138ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov for (int rw = 0; rw < 2; rw++) { 11419bbac0983f71293405af9692a83b52c4c8d2498Dmitry Vyukov // printf("thr=%d off=%d sz1=%d off2=%d rw=%d p=%p\n", 11519bbac0983f71293405af9692a83b52c4c8d2498Dmitry Vyukov // main, off, sz1, off2, rw, obj); 1168ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov access1(main, off, sz1, off2, rw, (char*)obj); 1178ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov obj += 2; 1188ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 1198ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 1208ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 1218ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 1228ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov} 1238ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 1248ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukovvoid *Thread(void *p) { 1258ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov (void)p; 1268ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov sleep(1); 1278ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov Test(false); 1288ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov return 0; 1298ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov} 1308ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 1318ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukovint main() { 1328ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov pthread_t th; 1338ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov pthread_create(&th, 0, Thread, 0); 1348ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov Test(true); 1358ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov pthread_join(th, 0); 1368ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov} 1378ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 13819bbac0983f71293405af9692a83b52c4c8d2498Dmitry Vyukov// CHECK: WARNING: ThreadSanitizer: data race 1398ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov// CHECK: ThreadSanitizer: reported 224 warnings 140