1 | // RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t && %run %t 2>&1 |
2 | // This is a correct program and tsan should not report a race. |
3 | // |
4 | // Verify that there is a happens-before relationship between a |
5 | // memory_order_release store that happens as part of a successful |
6 | // compare_exchange_strong(), and an atomic_thread_fence(memory_order_acquire) |
7 | // that happens after a relaxed load. |
8 | |
9 | #include <atomic> |
10 | #include <sanitizer/tsan_interface.h> |
11 | #include <stdbool.h> |
12 | #include <stdio.h> |
13 | #include <thread> |
14 | |
15 | std::atomic<bool> a; |
16 | unsigned int b; |
17 | constexpr int loops = 100000; |
18 | |
19 | void Thread1() { |
20 | for (int i = 0; i < loops; ++i) { |
21 | while (a.load(std::memory_order_acquire)) { |
22 | } |
23 | b = i; |
24 | bool expected = false; |
25 | a.compare_exchange_strong(expected, true, std::memory_order_acq_rel); |
26 | } |
27 | } |
28 | |
29 | int main() { |
30 | std::thread t(Thread1); |
31 | unsigned int sum = 0; |
32 | for (int i = 0; i < loops; ++i) { |
33 | while (!a.load(std::memory_order_relaxed)) { |
34 | } |
35 | std::atomic_thread_fence(std::memory_order_acquire); |
36 | __tsan_acquire(&a); |
37 | sum += b; |
38 | a.store(false, std::memory_order_release); |
39 | } |
40 | t.join(); |
41 | fprintf(stderr, format: "DONE: %u\n" , sum); |
42 | return 0; |
43 | } |
44 | |