From c8f7701516a5eb8cb4edd3d9e41ca6891dc386ef Mon Sep 17 00:00:00 2001 From: Matthieu Schaller <schaller@strw.leidenuniv.nl> Date: Thu, 30 Aug 2018 12:02:09 +0200 Subject: [PATCH] Added an atomic add for doubles-precision numbers. --- src/atomic.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/atomic.h b/src/atomic.h index 69df59e9fb..10548c6a20 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -127,4 +127,36 @@ __attribute__((always_inline)) INLINE static void atomic_add_f( } while (test_val.as_int != old_val.as_int); } +/** + * @brief Atomic add operation on doubles. + * + * This is a text-book implementation based on an atomic CAS. + * + * We create a temporary union to cope with the int-only atomic CAS + * and the floating-point add that we want. + * + * @param address The address to update. + * @param y The value to update the address with. + */ +__attribute__((always_inline)) INLINE static void atomic_add_d( + volatile double *const address, const double y) { + + long long *const long_long_ptr = (long long *)address; + + typedef union { + double as_double; + long long as_long_long; + } cast_type; + + cast_type test_val, old_val, new_val; + old_val.as_double = *address; + + do { + test_val.as_long_long = old_val.as_long_long; + new_val.as_double = old_val.as_double + y; + old_val.as_long_long = + atomic_cas(long_long_ptr, test_val.as_long_long, new_val.as_long_long); + } while (test_val.as_long_long != old_val.as_long_long); +} + #endif /* SWIFT_ATOMIC_H */ -- GitLab