236
|
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
|
|
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
|