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
9volatile long stop;
10long atomic, read_only, racy;
11int fds[2];
12
13__attribute__((noinline)) void *SecondaryThread(void *x) {
14 __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL);
15 return NULL;
16}
17
18void *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(fd: fds[1], buf: fds, n: 1);
39 }
40 if (me == 0 || me == 6) {
41 char buf[2];
42 read(fd: fds[0], buf: &buf, nbytes: sizeof(buf));
43 }
44 if (me == 0 || me == 7) {
45 pthread_t th;
46 pthread_create(newthread: &th, NULL, start_routine: SecondaryThread, NULL);
47 pthread_join(th: th, NULL);
48 }
49 if (me == 0 || me == 8) {
50 long buf;
51 memcpy(dest: &buf, src: &read_only, n: 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(file: "/dev/null", O_RDONLY);
63 if (fd != -1) {
64 close(fd: fd);
65 fd = -1;
66 }
67 }
68 // If you add more actions, update kActions in main.
69 }
70 return NULL;
71}
72
73int main() {
74 ANNOTATE_BENIGN_RACE(stop);
75 if (pipe(pipedes: fds))
76 exit(status: (perror(s: "pipe"), 1));
77 if (fcntl(fd: fds[0], F_SETFL, O_NONBLOCK))
78 exit(status: (perror(s: "fcntl"), 1));
79 if (fcntl(fd: fds[1], F_SETFL, O_NONBLOCK))
80 exit(status: (perror(s: "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(newthread: &t[i], NULL, start_routine: Thread, arg: (void *)(long)(i % kActions));
90 sleep(seconds: 5);
91 stop = 1;
92 for (int i = 0; i < kActions * kMultiplier; i++)
93 pthread_join(th: t[i], NULL);
94 fprintf(stderr, format: "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

source code of compiler-rt/test/tsan/stress.cpp