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 int fd = -1; 22 while (!stop) { 23 // If me == 0, we do all of the following, 24 // otherwise only 1 type of action. 25 if (me == 0 || me == 1) { 26 // just read the stop variable 27 } 28 if (me == 0 || me == 2) { 29 __atomic_store_n(&atomic, sink, __ATOMIC_RELEASE); 30 } 31 if (me == 0 || me == 3) { 32 sink += __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL); 33 } 34 if (me == 0 || me == 4) { 35 SecondaryThread(NULL); 36 } 37 if (me == 0 || me == 5) { 38 write(fds[1], fds, 1); 39 } 40 if (me == 0 || me == 6) { 41 char buf[2]; 42 read(fds[0], &buf, sizeof(buf)); 43 } 44 if (me == 0 || me == 7) { 45 pthread_t th; 46 pthread_create(&th, NULL, SecondaryThread, NULL); 47 pthread_join(th, NULL); 48 } 49 if (me == 0 || me == 8) { 50 long buf; 51 memcpy(&buf, &read_only, sizeof(buf)); 52 sink += buf; 53 } 54 if (me == 0 || me == 9) { 55 #if RACE 56 sink += racy++; 57 #else 58 sink += racy; 59 #endif 60 } 61 if (me == 0 || me == 10) { 62 fd = open("/dev/null", O_RDONLY); 63 if (fd != -1) { 64 close(fd); 65 fd = -1; 66 } 67 } 68 // If you add more actions, update kActions in main. 69 } 70 return NULL; 71 } 72 73 int main() { 74 ANNOTATE_BENIGN_RACE(stop); 75 if (pipe(fds)) 76 exit((perror("pipe"), 1)); 77 if (fcntl(fds[0], F_SETFL, O_NONBLOCK)) 78 exit((perror("fcntl"), 1)); 79 if (fcntl(fds[1], F_SETFL, O_NONBLOCK)) 80 exit((perror("fcntl"), 1)); 81 const int kActions = 11; 82 #if RACE 83 const int kMultiplier = 1; 84 #else 85 const int kMultiplier = 4; 86 #endif 87 pthread_t t[kActions * kMultiplier]; 88 for (int i = 0; i < kActions * kMultiplier; i++) 89 pthread_create(&t[i], NULL, Thread, (void *)(long)(i % kActions)); 90 sleep(5); 91 stop = 1; 92 for (int i = 0; i < kActions * kMultiplier; i++) 93 pthread_join(t[i], NULL); 94 fprintf(stderr, "DONE\n"); 95 return 0; 96 } 97 98 // CHECK-NORACE-NOT: ThreadSanitizer: 99 // CHECK-NORACE: DONE 100 // CHECK-NORACE-NOT: ThreadSanitizer: 101 // CHECK-RACE: ThreadSanitizer: data race 102 // CHECK-RACE: DONE 103