1 | // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s |
2 | #include "test.h" |
3 | |
4 | const int kTestCount = 4; |
5 | typedef long long T; |
6 | T atomics[kTestCount * 2]; |
7 | |
8 | void Test(int test, T *p, bool main_thread) { |
9 | volatile T sink; |
10 | if (test == 0) { |
11 | if (main_thread) |
12 | __atomic_fetch_add(p, 1, __ATOMIC_RELAXED); |
13 | else |
14 | __atomic_fetch_add(p, 1, __ATOMIC_RELAXED); |
15 | } else if (test == 1) { |
16 | if (main_thread) |
17 | __atomic_exchange_n(p, 1, __ATOMIC_ACQ_REL); |
18 | else |
19 | __atomic_exchange_n(p, 1, __ATOMIC_ACQ_REL); |
20 | } else if (test == 2) { |
21 | if (main_thread) |
22 | sink = __atomic_load_n(p, __ATOMIC_SEQ_CST); |
23 | else |
24 | __atomic_store_n(p, 1, __ATOMIC_SEQ_CST); |
25 | } else if (test == 3) { |
26 | if (main_thread) |
27 | sink = __atomic_load_n(p, __ATOMIC_SEQ_CST); |
28 | else |
29 | sink = *p; |
30 | } |
31 | } |
32 | |
33 | void *Thread(void *p) { |
34 | for (int i = 0; i < kTestCount; i++) { |
35 | Test(test: i, p: &atomics[i], main_thread: false); |
36 | } |
37 | barrier_wait(barrier: &barrier); |
38 | barrier_wait(barrier: &barrier); |
39 | for (int i = 0; i < kTestCount; i++) { |
40 | fprintf(stderr, format: "Test %d reverse\n" , i); |
41 | Test(test: i, p: &atomics[kTestCount + i], main_thread: false); |
42 | } |
43 | return 0; |
44 | } |
45 | |
46 | int main() { |
47 | barrier_init(barrier: &barrier, count: 2); |
48 | pthread_t t; |
49 | pthread_create(newthread: &t, attr: 0, start_routine: Thread, arg: 0); |
50 | barrier_wait(barrier: &barrier); |
51 | for (int i = 0; i < kTestCount; i++) { |
52 | fprintf(stderr, format: "Test %d\n" , i); |
53 | Test(test: i, p: &atomics[i], main_thread: true); |
54 | } |
55 | for (int i = 0; i < kTestCount; i++) { |
56 | Test(test: i, p: &atomics[kTestCount + i], main_thread: true); |
57 | } |
58 | barrier_wait(barrier: &barrier); |
59 | pthread_join(th: t, thread_return: 0); |
60 | } |
61 | |
62 | // CHECK-NOT: ThreadSanitizer: data race |
63 | |