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