1 // 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
9 #define NUM_THREADS NUM_ORDS * 2
13 std::atomic
<node
*> _nodes
[NUM_THREADS
] = {};
18 _nodes
[i
].store(n
, std::memory_order_release
);
21 template <int version
>
22 void f2(int i
, std::memory_order mo
, std::memory_order fmo
) {
23 node
*expected
= nullptr;
24 while (expected
== nullptr) {
25 _nodes
[i
].compare_exchange_weak(expected
, nullptr, mo
, fmo
);
29 assert(expected
->val
== 43);
32 struct MemOrdSuccFail
{
34 std::memory_order fmo
;
37 MemOrdSuccFail OrdList
[NUM_ORDS
] = {
38 {std::memory_order_release
, std::memory_order_relaxed
},
39 {std::memory_order_release
, std::memory_order_acquire
},
40 {std::memory_order_release
, std::memory_order_consume
},
41 {std::memory_order_release
, std::memory_order_seq_cst
},
43 {std::memory_order_acq_rel
, std::memory_order_relaxed
},
44 {std::memory_order_acq_rel
, std::memory_order_acquire
},
45 {std::memory_order_acq_rel
, std::memory_order_consume
},
46 {std::memory_order_acq_rel
, std::memory_order_seq_cst
},
48 {std::memory_order_seq_cst
, std::memory_order_relaxed
},
49 {std::memory_order_seq_cst
, std::memory_order_acquire
},
50 {std::memory_order_seq_cst
, std::memory_order_consume
},
51 {std::memory_order_seq_cst
, std::memory_order_seq_cst
},
53 {std::memory_order_relaxed
, std::memory_order_relaxed
},
54 {std::memory_order_relaxed
, std::memory_order_acquire
},
55 {std::memory_order_relaxed
, std::memory_order_consume
},
56 {std::memory_order_relaxed
, std::memory_order_seq_cst
},
60 std::thread threads
[NUM_THREADS
];
63 // Instantiate a new f2 for each MO so we can dedup reports and actually
64 // make sure relaxed FMO triggers a warning for every different MO.
65 for (unsigned t
= 0; t
< 8; t
+= 2) {
66 threads
[t
] = std::thread(f1
, t
);
67 threads
[t
+ 1] = std::thread(f2
<0>, t
, OrdList
[ords
].mo
, OrdList
[ords
].fmo
);
69 threads
[t
+ 1].join();
73 for (unsigned t
= 8; t
< 16; t
+= 2) {
74 threads
[t
] = std::thread(f1
, t
);
75 threads
[t
+ 1] = std::thread(f2
<1>, t
, OrdList
[ords
].mo
, OrdList
[ords
].fmo
);
77 threads
[t
+ 1].join();
81 for (unsigned t
= 16; t
< 24; t
+= 2) {
82 threads
[t
] = std::thread(f1
, t
);
83 threads
[t
+ 1] = std::thread(f2
<2>, t
, OrdList
[ords
].mo
, OrdList
[ords
].fmo
);
85 threads
[t
+ 1].join();
89 for (unsigned t
= 24; t
< 32; t
+= 2) {
90 threads
[t
] = std::thread(f1
, t
);
91 threads
[t
+ 1] = std::thread(f2
<3>, t
, OrdList
[ords
].mo
, OrdList
[ords
].fmo
);
93 threads
[t
+ 1].join();
97 fprintf(stderr
, "DONE\n");
101 // CHECK-REPORT: WARNING: ThreadSanitizer: data race
102 // CHECK-REPORT: WARNING: ThreadSanitizer: data race
103 // CHECK-REPORT: WARNING: ThreadSanitizer: data race
104 // CHECK-REPORT: WARNING: ThreadSanitizer: data race
105 // CHECK-REPORT: DONE
106 // CHECK-REPORT: ThreadSanitizer: reported 4 warnings