Commit 047fe58a53

kcbanner <kcbanner@gmail.com>
2022-12-17 06:27:34
cbe: fix msvc cmpxchg implementations
1 parent 4f8f7b7
Changed files (1)
lib
lib/zig.h
@@ -196,7 +196,7 @@ typedef char bool;
 #define memory_order_acq_rel 4
 #define memory_order_seq_cst 5
 #define zig_atomic(type) type
-#define zig_cmpxchg_strong(obj, expected, desired, succ, fail, type) zig_expand_concat(zig_msvc_cmpxchg_, type)(obj, expected, desired)
+#define zig_cmpxchg_strong(obj, expected, desired, succ, fail, type) zig_expand_concat(zig_msvc_cmpxchg_, type)(obj, &(expected), desired)
 #define   zig_cmpxchg_weak(obj, expected, desired, succ, fail, type) zig_cmpxchg_strong(obj, expected, desired, succ, fail, type)
 #define zig_atomicrmw_xchg(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_xchg_, type)(obj, arg)
 #define  zig_atomicrmw_add(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_add_, type)(obj, arg)
@@ -2096,12 +2096,18 @@ zig_float_builtins(c_longdouble)
 #if _MSC_VER && (_M_IX86 || _M_X64)
 #include <intrin.h>
 
-// TODO: zig_msvc_atomic_load should load 32 bit without interlocked on x86, load 64 bit without interlocked on x64
-// TODO: Fix obviously broken nand / min / max, these don't exist on msvc _InterlockedNand
+// TODO: zig_msvc_atomic_load should just load 32 bit without interlocked on x86, and just load 64 bit without interlocked on x64
+// TODO: Fix obviously broken nand / min / max, these don't exist on msvc
 
 #define zig_msvc_atomics(type, suffix) \
-    static inline bool zig_msvc_cmpxchg_##type(zig_##type volatile* obj, zig_##type expected, zig_##type desired) { \
-        return _InterlockedCompareExchange##suffix(obj, desired, expected) == expected; \
+    static inline bool zig_msvc_cmpxchg_##type(zig_##type volatile* obj, zig_##type* expected, zig_##type desired) { \
+        zig_##type comparand = *expected; \
+        zig_##type initial = _InterlockedCompareExchange##suffix(obj, desired, comparand); \
+        bool exchanged = initial == comparand; \
+        if (!exchanged) { \
+            *expected = initial; \
+        } \
+        return exchanged; \
     } \
     static inline zig_##type zig_msvc_atomicrmw_xchg_##type(zig_##type volatile* obj, zig_##type value) { \
         return _InterlockedExchange##suffix(obj, value); \
@@ -2146,12 +2152,24 @@ zig_msvc_atomics(i32, )
 zig_msvc_atomics(u64, 64)
 zig_msvc_atomics(i64, 64)
 
-static inline bool zig_msvc_cmpxchg_p32(void** obj, void* expected, void* desired) {
-    return _InterlockedCompareExchangePointer(obj, desired, expected) == expected;
+static inline bool zig_msvc_cmpxchg_p32(void** obj, void** expected, void* desired) {
+    void* comparand = *expected;
+    void* initial = _InterlockedCompareExchangePointer(obj, desired, comparand);
+    bool exchanged = initial == comparand;
+    if (!exchanged) {
+        *expected = initial;
+    }
+    return exchanged;
 }
 
-static inline bool zig_msvc_cmpxchg_p64(void** obj, void* expected, void* desired) {
-    return _InterlockedCompareExchangePointer(obj, desired, expected) == expected;
+static inline bool zig_msvc_cmpxchg_p64(void** obj, void** expected, void* desired) {
+    void* comparand = *expected;
+    void* initial = _InterlockedCompareExchangePointer(obj, desired, comparand);
+    bool exchanged = initial == comparand;
+    if (!exchanged) {
+        *expected = initial;
+    }
+    return exchanged;
 }
 
 #if _M_IX86
@@ -2180,13 +2198,11 @@ static inline void* zig_msvc_atomic_load_p64(void** obj) {
 }
 #endif
 
-static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128 expected, zig_u128 desired) {
-    zig_u128 comparand_result = desired;
-    return _InterlockedCompareExchange128((zig_i64 volatile*)obj, expected.hi, expected.lo, (zig_i64*)&comparand_result);
+static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128* expected, zig_u128 desired) {
+    return _InterlockedCompareExchange128((zig_i64 volatile*)obj, desired.hi, desired.lo, (zig_i64*)expected);
 }
 
-static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128 expected, zig_i128 desired) {
-    zig_i128 comparand_result = desired;
-    return _InterlockedCompareExchange128((zig_i64 volatile*)obj, expected.hi, expected.lo, (zig_u64*)&comparand_result);
+static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128* expected, zig_i128 desired) {
+    return _InterlockedCompareExchange128((zig_i64 volatile*)obj, desired.hi, desired.lo, (zig_u64*)expected);
 }
 #endif