[libc-commits] [libc] [libc][CPP] correct cmpxchg failure ordering inference (PR #133127)

Schrodinger ZHU Yifan via libc-commits libc-commits at lists.llvm.org
Wed Mar 26 10:14:04 PDT 2025


https://github.com/SchrodingerZhu created https://github.com/llvm/llvm-project/pull/133127

None

>From 46f0710ca04a670846e85e7de8163f8d9667c4fc Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Wed, 26 Mar 2025 13:12:56 -0400
Subject: [PATCH] [libc][CPP] correct cmpxchg failure ordering inference

---
 libc/src/__support/CPP/atomic.h | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/libc/src/__support/CPP/atomic.h b/libc/src/__support/CPP/atomic.h
index 15242a131c63b..3a30c7d33faea 100644
--- a/libc/src/__support/CPP/atomic.h
+++ b/libc/src/__support/CPP/atomic.h
@@ -62,6 +62,14 @@ template <typename T> struct Atomic {
     return static_cast<int>(mem_scope);
   }
 
+  LIBC_INLINE static constexpr int infer_failure_order(MemoryOrder mem_ord) {
+    if (mem_ord == MemoryOrder::RELEASE)
+      return order(MemoryOrder::RELAXED);
+    if (mem_ord == MemoryOrder::ACQ_REL)
+      return order(MemoryOrder::ACQUIRE);
+    return order(mem_ord);
+  }
+
   LIBC_INLINE static T *addressof(T &ref) { return __builtin_addressof(ref); }
 
   // Require types that are 1, 2, 4, 8, or 16 bytes in length to be aligned to
@@ -129,7 +137,7 @@ template <typename T> struct Atomic {
       [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
     return __atomic_compare_exchange(addressof(val), addressof(expected),
                                      addressof(desired), false, order(mem_ord),
-                                     order(mem_ord));
+                                     infer_failure_order(mem_ord));
   }
 
   // Atomic compare exchange (separate success and failure memory orders)
@@ -148,7 +156,7 @@ template <typename T> struct Atomic {
       [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
     return __atomic_compare_exchange(addressof(val), addressof(expected),
                                      addressof(desired), true, order(mem_ord),
-                                     order(mem_ord));
+                                     infer_failure_order(mem_ord));
   }
 
   // Atomic compare exchange (weak version with separate success and failure
@@ -252,6 +260,14 @@ template <typename T> struct AtomicRef {
     return static_cast<int>(mem_scope);
   }
 
+  LIBC_INLINE static constexpr int infer_failure_order(MemoryOrder mem_ord) {
+    if (mem_ord == MemoryOrder::RELEASE)
+      return order(MemoryOrder::RELAXED);
+    if (mem_ord == MemoryOrder::ACQ_REL)
+      return order(MemoryOrder::ACQUIRE);
+    return order(mem_ord);
+  }
+
 public:
   // Constructor from T reference
   LIBC_INLINE explicit constexpr AtomicRef(T &obj) : ptr(&obj) {}
@@ -298,7 +314,8 @@ template <typename T> struct AtomicRef {
       T &expected, T desired, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
       [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) const {
     return __atomic_compare_exchange(ptr, &expected, &desired, false,
-                                     order(mem_ord), order(mem_ord));
+                                     order(mem_ord),
+                                     infer_failure_order(mem_ord));
   }
 
   // Atomic compare exchange (strong, separate success/failure memory orders)



More information about the libc-commits mailing list