1*fd184c06SBruno Cardoso Lopes // RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t && %deflake %env_tsan_opts=atexit_sleep_ms=50 %run %t 2>&1 | FileCheck --check-prefix=CHECK-REPORT %s
2*fd184c06SBruno Cardoso Lopes
3*fd184c06SBruno Cardoso Lopes #include <atomic>
4*fd184c06SBruno Cardoso Lopes #include <cassert>
5*fd184c06SBruno Cardoso Lopes #include <stdio.h>
6*fd184c06SBruno Cardoso Lopes #include <thread>
7*fd184c06SBruno Cardoso Lopes
8*fd184c06SBruno Cardoso Lopes #define NUM_ORDS 16
9*fd184c06SBruno Cardoso Lopes #define NUM_THREADS NUM_ORDS * 2
10*fd184c06SBruno Cardoso Lopes struct node {
11*fd184c06SBruno Cardoso Lopes int val;
12*fd184c06SBruno Cardoso Lopes };
13*fd184c06SBruno Cardoso Lopes std::atomic<node *> _nodes[NUM_THREADS] = {};
14*fd184c06SBruno Cardoso Lopes
f1(int i)15*fd184c06SBruno Cardoso Lopes void f1(int i) {
16*fd184c06SBruno Cardoso Lopes auto n = new node();
17*fd184c06SBruno Cardoso Lopes n->val = 42;
18*fd184c06SBruno Cardoso Lopes _nodes[i].store(n, std::memory_order_release);
19*fd184c06SBruno Cardoso Lopes }
20*fd184c06SBruno Cardoso Lopes
21*fd184c06SBruno Cardoso Lopes template <int version>
f2(int i,std::memory_order mo,std::memory_order fmo)22*fd184c06SBruno Cardoso Lopes void f2(int i, std::memory_order mo, std::memory_order fmo) {
23*fd184c06SBruno Cardoso Lopes node *expected = nullptr;
24*fd184c06SBruno Cardoso Lopes while (expected == nullptr) {
25*fd184c06SBruno Cardoso Lopes _nodes[i].compare_exchange_weak(expected, nullptr, mo, fmo);
26*fd184c06SBruno Cardoso Lopes };
27*fd184c06SBruno Cardoso Lopes
28*fd184c06SBruno Cardoso Lopes ++expected->val;
29*fd184c06SBruno Cardoso Lopes assert(expected->val == 43);
30*fd184c06SBruno Cardoso Lopes }
31*fd184c06SBruno Cardoso Lopes
32*fd184c06SBruno Cardoso Lopes struct MemOrdSuccFail {
33*fd184c06SBruno Cardoso Lopes std::memory_order mo;
34*fd184c06SBruno Cardoso Lopes std::memory_order fmo;
35*fd184c06SBruno Cardoso Lopes };
36*fd184c06SBruno Cardoso Lopes
37*fd184c06SBruno Cardoso Lopes MemOrdSuccFail OrdList[NUM_ORDS] = {
38*fd184c06SBruno Cardoso Lopes {std::memory_order_release, std::memory_order_relaxed},
39*fd184c06SBruno Cardoso Lopes {std::memory_order_release, std::memory_order_acquire},
40*fd184c06SBruno Cardoso Lopes {std::memory_order_release, std::memory_order_consume},
41*fd184c06SBruno Cardoso Lopes {std::memory_order_release, std::memory_order_seq_cst},
42*fd184c06SBruno Cardoso Lopes
43*fd184c06SBruno Cardoso Lopes {std::memory_order_acq_rel, std::memory_order_relaxed},
44*fd184c06SBruno Cardoso Lopes {std::memory_order_acq_rel, std::memory_order_acquire},
45*fd184c06SBruno Cardoso Lopes {std::memory_order_acq_rel, std::memory_order_consume},
46*fd184c06SBruno Cardoso Lopes {std::memory_order_acq_rel, std::memory_order_seq_cst},
47*fd184c06SBruno Cardoso Lopes
48*fd184c06SBruno Cardoso Lopes {std::memory_order_seq_cst, std::memory_order_relaxed},
49*fd184c06SBruno Cardoso Lopes {std::memory_order_seq_cst, std::memory_order_acquire},
50*fd184c06SBruno Cardoso Lopes {std::memory_order_seq_cst, std::memory_order_consume},
51*fd184c06SBruno Cardoso Lopes {std::memory_order_seq_cst, std::memory_order_seq_cst},
52*fd184c06SBruno Cardoso Lopes
53*fd184c06SBruno Cardoso Lopes {std::memory_order_relaxed, std::memory_order_relaxed},
54*fd184c06SBruno Cardoso Lopes {std::memory_order_relaxed, std::memory_order_acquire},
55*fd184c06SBruno Cardoso Lopes {std::memory_order_relaxed, std::memory_order_consume},
56*fd184c06SBruno Cardoso Lopes {std::memory_order_relaxed, std::memory_order_seq_cst},
57*fd184c06SBruno Cardoso Lopes };
58*fd184c06SBruno Cardoso Lopes
main()59*fd184c06SBruno Cardoso Lopes int main() {
60*fd184c06SBruno Cardoso Lopes std::thread threads[NUM_THREADS];
61*fd184c06SBruno Cardoso Lopes int ords = 0;
62*fd184c06SBruno Cardoso Lopes
63*fd184c06SBruno Cardoso Lopes // Instantiate a new f2 for each MO so we can dedup reports and actually
64*fd184c06SBruno Cardoso Lopes // make sure relaxed FMO triggers a warning for every different MO.
65*fd184c06SBruno Cardoso Lopes for (unsigned t = 0; t < 8; t += 2) {
66*fd184c06SBruno Cardoso Lopes threads[t] = std::thread(f1, t);
67*fd184c06SBruno Cardoso Lopes threads[t + 1] = std::thread(f2<0>, t, OrdList[ords].mo, OrdList[ords].fmo);
68*fd184c06SBruno Cardoso Lopes threads[t].join();
69*fd184c06SBruno Cardoso Lopes threads[t + 1].join();
70*fd184c06SBruno Cardoso Lopes ords++;
71*fd184c06SBruno Cardoso Lopes }
72*fd184c06SBruno Cardoso Lopes
73*fd184c06SBruno Cardoso Lopes for (unsigned t = 8; t < 16; t += 2) {
74*fd184c06SBruno Cardoso Lopes threads[t] = std::thread(f1, t);
75*fd184c06SBruno Cardoso Lopes threads[t + 1] = std::thread(f2<1>, t, OrdList[ords].mo, OrdList[ords].fmo);
76*fd184c06SBruno Cardoso Lopes threads[t].join();
77*fd184c06SBruno Cardoso Lopes threads[t + 1].join();
78*fd184c06SBruno Cardoso Lopes ords++;
79*fd184c06SBruno Cardoso Lopes }
80*fd184c06SBruno Cardoso Lopes
81*fd184c06SBruno Cardoso Lopes for (unsigned t = 16; t < 24; t += 2) {
82*fd184c06SBruno Cardoso Lopes threads[t] = std::thread(f1, t);
83*fd184c06SBruno Cardoso Lopes threads[t + 1] = std::thread(f2<2>, t, OrdList[ords].mo, OrdList[ords].fmo);
84*fd184c06SBruno Cardoso Lopes threads[t].join();
85*fd184c06SBruno Cardoso Lopes threads[t + 1].join();
86*fd184c06SBruno Cardoso Lopes ords++;
87*fd184c06SBruno Cardoso Lopes }
88*fd184c06SBruno Cardoso Lopes
89*fd184c06SBruno Cardoso Lopes for (unsigned t = 24; t < 32; t += 2) {
90*fd184c06SBruno Cardoso Lopes threads[t] = std::thread(f1, t);
91*fd184c06SBruno Cardoso Lopes threads[t + 1] = std::thread(f2<3>, t, OrdList[ords].mo, OrdList[ords].fmo);
92*fd184c06SBruno Cardoso Lopes threads[t].join();
93*fd184c06SBruno Cardoso Lopes threads[t + 1].join();
94*fd184c06SBruno Cardoso Lopes ords++;
95*fd184c06SBruno Cardoso Lopes }
96*fd184c06SBruno Cardoso Lopes
97*fd184c06SBruno Cardoso Lopes fprintf(stderr, "DONE\n");
98*fd184c06SBruno Cardoso Lopes return 0;
99*fd184c06SBruno Cardoso Lopes }
100*fd184c06SBruno Cardoso Lopes
101*fd184c06SBruno Cardoso Lopes // CHECK-REPORT: WARNING: ThreadSanitizer: data race
102*fd184c06SBruno Cardoso Lopes // CHECK-REPORT: WARNING: ThreadSanitizer: data race
103*fd184c06SBruno Cardoso Lopes // CHECK-REPORT: WARNING: ThreadSanitizer: data race
104*fd184c06SBruno Cardoso Lopes // CHECK-REPORT: WARNING: ThreadSanitizer: data race
105*fd184c06SBruno Cardoso Lopes // CHECK-REPORT: DONE
106*fd184c06SBruno Cardoso Lopes // CHECK-REPORT: ThreadSanitizer: reported 4 warnings
107