1 | // RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | 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 | *p = 42; |
15 | } else if (test == 1) { |
16 | if (main_thread) |
17 | __atomic_fetch_add(p, 1, __ATOMIC_RELAXED); |
18 | else |
19 | sink = *p; |
20 | } else if (test == 2) { |
21 | if (main_thread) |
22 | sink = __atomic_load_n(p, __ATOMIC_SEQ_CST); |
23 | else |
24 | *p = 42; |
25 | } else if (test == 3) { |
26 | if (main_thread) |
27 | __atomic_store_n(p, 1, __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: Test 0 |
63 | // CHECK: ThreadSanitizer: data race |
64 | // CHECK-NOT: SUMMARY{{.*}}tsan_interface_atomic |
65 | // CHECK: Test 1 |
66 | // CHECK: ThreadSanitizer: data race |
67 | // CHECK-NOT: SUMMARY{{.*}}tsan_interface_atomic |
68 | // CHECK: Test 2 |
69 | // CHECK: ThreadSanitizer: data race |
70 | // CHECK-NOT: SUMMARY{{.*}}tsan_interface_atomic |
71 | // CHECK: Test 3 |
72 | // CHECK: ThreadSanitizer: data race |
73 | // CHECK-NOT: SUMMARY{{.*}}tsan_interface_atomic |
74 | // CHECK: Test 0 reverse |
75 | // CHECK: ThreadSanitizer: data race |
76 | // CHECK: Test 1 reverse |
77 | // CHECK: ThreadSanitizer: data race |
78 | // CHECK: Test 2 reverse |
79 | // CHECK: ThreadSanitizer: data race |
80 | // CHECK: Test 3 reverse |
81 | // CHECK: ThreadSanitizer: data race |
82 | |