1 // This run stresses global reset happenning concurrently with everything else. 2 // RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=flush_memory_ms=1:flush_symbolizer_ms=1:memory_limit_mb=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NORACE 3 // This run stresses race reporting happenning concurrently with everything else. 4 // RUN: %clangxx_tsan -O1 %s -DRACE=1 -o %t && %env_tsan_opts=suppress_equal_stacks=0:suppress_equal_addresses=0 %deflake %run %t | FileCheck %s --check-prefix=CHECK-RACE 5 #include "test.h" 6 #include <fcntl.h> 7 #include <string.h> 8 9 volatile long stop; 10 long atomic, read_only, racy; 11 int fds[2]; 12 13 __attribute__((noinline)) void *SecondaryThread(void *x) { 14 __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL); 15 return NULL; 16 } 17 18 void *Thread(void *x) { 19 const int me = (long)x; 20 volatile long sink = 0; 21 while (!stop) { 22 // If me == 0, we do all of the following, 23 // otherwise only 1 type of action. 24 if (me == 0 || me == 1) { 25 // just read the stop variable 26 } 27 if (me == 0 || me == 2) { 28 __atomic_store_n(&atomic, sink, __ATOMIC_RELEASE); 29 } 30 if (me == 0 || me == 3) { 31 sink += __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL); 32 } 33 if (me == 0 || me == 4) { 34 SecondaryThread(NULL); 35 } 36 if (me == 0 || me == 5) { 37 write(fds[1], fds, 1); 38 } 39 if (me == 0 || me == 6) { 40 char buf[2]; 41 read(fds[0], &buf, sizeof(buf)); 42 } 43 if (me == 0 || me == 7) { 44 pthread_t th; 45 pthread_create(&th, NULL, SecondaryThread, NULL); 46 pthread_join(th, NULL); 47 } 48 if (me == 0 || me == 8) { 49 long buf; 50 memcpy(&buf, &read_only, sizeof(buf)); 51 sink += buf; 52 } 53 if (me == 0 || me == 9) { 54 #if RACE 55 sink += racy++; 56 #else 57 sink += racy; 58 #endif 59 } 60 // If you add more actions, update kActions in main. 61 } 62 return NULL; 63 } 64 65 int main() { 66 ANNOTATE_BENIGN_RACE(stop); 67 if (pipe(fds)) 68 exit((perror("pipe"), 1)); 69 if (fcntl(fds[0], F_SETFL, O_NONBLOCK)) 70 exit((perror("fcntl"), 1)); 71 if (fcntl(fds[1], F_SETFL, O_NONBLOCK)) 72 exit((perror("fcntl"), 1)); 73 const int kActions = 10; 74 #if RACE 75 const int kMultiplier = 1; 76 #else 77 const int kMultiplier = 4; 78 #endif 79 pthread_t t[kActions * kMultiplier]; 80 for (int i = 0; i < kActions * kMultiplier; i++) 81 pthread_create(&t[i], NULL, Thread, (void *)(long)(i % kActions)); 82 sleep(5); 83 stop = 1; 84 for (int i = 0; i < kActions * kMultiplier; i++) 85 pthread_join(t[i], NULL); 86 fprintf(stderr, "DONE\n"); 87 return 0; 88 } 89 90 // CHECK-NORACE-NOT: ThreadSanitizer: 91 // CHECK-NORACE: DONE 92 // CHECK-NORACE-NOT: ThreadSanitizer: 93 // CHECK-RACE: ThreadSanitizer: data race 94 // CHECK-RACE: DONE 95