From e3a01e02259ca0bb423631db56c71ded37ad5225 Mon Sep 17 00:00:00 2001
From: Matthieu Schaller <schaller@strw.leidenuniv.nl>
Date: Wed, 9 May 2018 14:16:54 +0200
Subject: [PATCH] Fixed the atomic min/max/add for floats that were incorrectly
 pushed earlier.

---
 src/atomic.h | 51 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 30 insertions(+), 21 deletions(-)

diff --git a/src/atomic.h b/src/atomic.h
index 4e3407cc33..36e336b721 100644
--- a/src/atomic.h
+++ b/src/atomic.h
@@ -35,39 +35,48 @@
 #define atomic_swap(v, n) __sync_lock_test_and_set(v, n)
 
 /**
- * @param Atomic min operation on floats.
+ * @brief Atomic min operation on floats.
  */
-__attribute__((always_inline)) INLINE void atomic_min_f(float const* x,
+__attribute__((always_inline)) INLINE void atomic_min_f(volatile float* x,
                                                         float y) {
-  int done = 0;
-  while (!done) {
-    const float val = *x;
-    done = __sync_bool_compare_and_swap((int*)x, val, min(val, y));
-  }
+  float test, new;
+  float old = *x;
+  do {
+    test = old;
+    new = min(old, y);
+    if (new == old) return;
+    old = atomic_cas((int*)x, test, new);
+  } while (test != old);
 }
 
 /**
- * @param Atomic max operation on floats.
+ * @brief Atomic max operation on floats.
  */
-__attribute__((always_inline)) INLINE void atomic_max_f(float const* x,
+__attribute__((always_inline)) INLINE void atomic_max_f(volatile float* x,
                                                         float y) {
-  int done = 0;
-  while (!done) {
-    const float val = *x;
-    done = __sync_bool_compare_and_swap((int*)x, val, max(val, y));
-  }
+  float test, new;
+  float old = *x;
+  do {
+    test = old;
+    new = max(old, y);
+    if (new == old) return;
+    old = atomic_cas((int*)x, test, new);
+  } while (test != old);
 }
 
 /**
- * @param Atomic add operation on floats.
+ * @brief Atomic add operation on floats.
  */
-__attribute__((always_inline)) INLINE void atomic_add_f(float const* x,
+__attribute__((always_inline)) INLINE void atomic_add_f(volatile float* x,
                                                         float y) {
-  int done = 0;
-  while (!done) {
-    const float val = *x;
-    done = __sync_bool_compare_and_swap((int*)x, val, val + y);
-  }
+  float test, new;
+  float old = *x;
+  do {
+    test = old;
+    new = old + y;
+    if (new == old) return;
+    old = atomic_cas((int*)x, test, new);
+  } while (test != old);
 }
 
 #endif /* SWIFT_ATOMIC_H */
-- 
GitLab