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