xref: /llvm-project/compiler-rt/test/tsan/stress.cpp (revision 7505cc301f718c3a4015595729609aadcd702890)
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 %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 
SecondaryThread(void * x)13 __attribute__((noinline)) void *SecondaryThread(void *x) {
14   __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL);
15   return NULL;
16 }
17 
Thread(void * x)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 
main()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