1 // 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
2 #include "test.h"
3 #include <fcntl.h>
4 #include <string.h>
5 
6 volatile long stop;
7 long atomic, read_only;
8 int fds[2];
9 
10 __attribute__((noinline)) void *SecondaryThread(void *x) {
11   __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL);
12   return NULL;
13 }
14 
15 void *Thread(void *x) {
16   const int me = (long)x;
17   volatile long sink = 0;
18   while (!stop) {
19     // If me == 0, we do all of the following,
20     // otherwise only 1 type of action.
21     if (me == 0 || me == 1) {
22       // just read the stop variable
23     }
24     if (me == 0 || me == 2) {
25       __atomic_store_n(&atomic, 1, __ATOMIC_RELEASE);
26     }
27     if (me == 0 || me == 3) {
28       sink += __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL);
29     }
30     if (me == 0 || me == 4) {
31       SecondaryThread(NULL);
32     }
33     if (me == 0 || me == 5) {
34       write(fds[1], fds, 1);
35     }
36     if (me == 0 || me == 6) {
37       char buf[2];
38       read(fds[0], &buf, sizeof(buf));
39     }
40     if (me == 0 || me == 7) {
41       pthread_t th;
42       pthread_create(&th, NULL, SecondaryThread, NULL);
43       pthread_join(th, NULL);
44     }
45     if (me == 0 || me == 8) {
46       long buf;
47       memcpy(&buf, &read_only, sizeof(buf));
48       sink += buf;
49     }
50     // If you add more actions, update kActions in main.
51   }
52   return NULL;
53 }
54 
55 int main() {
56   ANNOTATE_BENIGN_RACE(stop);
57   if (pipe(fds))
58     exit((perror("pipe"), 1));
59   if (fcntl(fds[0], F_SETFL, O_NONBLOCK))
60     exit((perror("fcntl"), 1));
61   if (fcntl(fds[1], F_SETFL, O_NONBLOCK))
62     exit((perror("fcntl"), 1));
63   const int kActions = 9;
64   const int kMultiplier = 4;
65   pthread_t t[kActions * kMultiplier];
66   for (int i = 0; i < kActions * kMultiplier; i++)
67     pthread_create(&t[i], NULL, Thread, (void *)(long)(i % kActions));
68   sleep(5);
69   stop = 1;
70   for (int i = 0; i < kActions * kMultiplier; i++)
71     pthread_join(t[i], NULL);
72   fprintf(stderr, "DONE\n");
73   return 0;
74 }
75 
76 // CHECK-NOT: ThreadSanitizer:
77 // CHECK: DONE
78 // CHECK-NOT: ThreadSanitizer:
79