summaryrefslogtreecommitdiffstats
path: root/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp')
-rw-r--r--compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp43
1 files changed, 43 insertions, 0 deletions
diff --git a/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp b/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp
new file mode 100644
index 000000000000..b9fd0c5ad21f
--- /dev/null
+++ b/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp
@@ -0,0 +1,43 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1
+// This is a correct program and tsan should not report a race.
+//
+// Verify that there is a happens-before relationship between a
+// memory_order_release store that happens as part of a successful
+// compare_exchange_strong(), and an atomic_thread_fence(memory_order_acquire)
+// that happens after a relaxed load.
+
+#include <atomic>
+#include <sanitizer/tsan_interface.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <thread>
+
+std::atomic<bool> a;
+unsigned int b;
+constexpr int loops = 100000;
+
+void Thread1() {
+ for (int i = 0; i < loops; ++i) {
+ while (a.load(std::memory_order_acquire)) {
+ }
+ b = i;
+ bool expected = false;
+ a.compare_exchange_strong(expected, true, std::memory_order_acq_rel);
+ }
+}
+
+int main() {
+ std::thread t(Thread1);
+ unsigned int sum = 0;
+ for (int i = 0; i < loops; ++i) {
+ while (!a.load(std::memory_order_relaxed)) {
+ }
+ std::atomic_thread_fence(std::memory_order_acquire);
+ __tsan_acquire(&a);
+ sum += b;
+ a.store(false, std::memory_order_release);
+ }
+ t.join();
+ fprintf(stderr, "DONE: %u\n", sum);
+ return 0;
+}