From 3379d0e898149f5adf5d41eb64ca66c474521aea Mon Sep 17 00:00:00 2001
From: Matthieu Schaller <schaller@strw.leidenuniv.nl>
Date: Wed, 9 May 2018 18:21:01 +0200
Subject: [PATCH] Cleaner implementation of the atomic operations for floats.

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

diff --git a/src/atomic.h b/src/atomic.h
index 1007f72fac..6af25c7180 100644
--- a/src/atomic.h
+++ b/src/atomic.h
@@ -36,44 +36,86 @@
 
 /**
  * @brief Atomic min operation on floats.
+ *
+ * This is a text-book implementation based on an atomic CAS.
+ *
+ * @param address The address to update.
+ * @param y The value to update the address with.
  */
 __attribute__((always_inline)) INLINE static void atomic_min_f(
-    volatile float* x, float y) {
-  float test, new;
-  float old = *x;
+    volatile float* address, float y) {
+
+  int* int_ptr = (int*)address;
+
+  typedef union {
+    float as_float;
+    int as_int;
+  } cast_type;
+
+  cast_type assumed, old, new;
+  old.as_float = *address;
+
   do {
-    test = old;
-    new = min(old, y);
-    old = atomic_cas((int*)x, test, new);
-  } while (test != old);
+    assumed.as_int = old.as_int;
+    new.as_float = min(old.as_float, y);
+    old.as_int = atomic_cas(int_ptr, assumed.as_int, new.as_int);
+  } while (assumed.as_int != old.as_int);
 }
 
 /**
  * @brief Atomic max operation on floats.
+ *
+ * This is a text-book implementation based on an atomic CAS.
+ *
+ * @param address The address to update.
+ * @param y The value to update the address with.
  */
 __attribute__((always_inline)) INLINE static void atomic_max_f(
-    volatile float* x, float y) {
-  float test, new;
-  float old = *x;
+    volatile float* address, float y) {
+
+  int* int_ptr = (int*)address;
+
+  typedef union {
+    float as_float;
+    int as_int;
+  } cast_type;
+
+  cast_type assumed, old, new;
+  old.as_float = *address;
+
   do {
-    test = old;
-    new = max(old, y);
-    old = atomic_cas((int*)x, test, new);
-  } while (test != old);
+    assumed.as_int = old.as_int;
+    new.as_float = max(old.as_float, y);
+    old.as_int = atomic_cas(int_ptr, assumed.as_int, new.as_int);
+  } while (assumed.as_int != old.as_int);
 }
 
 /**
  * @brief Atomic add operation on floats.
+ *
+ * This is a text-book implementation based on an atomic CAS.
+ *
+ * @param address The address to update.
+ * @param y The value to update the address with.
  */
 __attribute__((always_inline)) INLINE static void atomic_add_f(
-    volatile float* x, float y) {
-  float test, new;
-  float old = *x;
+    volatile float* address, float y) {
+
+  int* int_ptr = (int*)address;
+
+  typedef union {
+    float as_float;
+    int as_int;
+  } cast_type;
+
+  cast_type assumed, old, new;
+  old.as_float = *address;
+
   do {
-    test = old;
-    new = old + y;
-    old = atomic_cas((int*)x, test, new);
-  } while (test != old);
+    assumed.as_int = old.as_int;
+    new.as_float = old.as_float + y;
+    old.as_int = atomic_cas(int_ptr, assumed.as_int, new.as_int);
+  } while (assumed.as_int != old.as_int);
 }
 
 #endif /* SWIFT_ATOMIC_H */
-- 
GitLab