From 8b8aae372db1775bda6a84605c7d68b8d1ed3402 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Fri, 22 Dec 2017 09:56:21 -0700 Subject: [PATCH] opal/asm: add atomic min/max convenience functions This commit adds atomic functions for min/max. Signed-off-by: Nathan Hjelm --- opal/include/opal/sys/atomic.h | 10 +++- opal/include/opal/sys/atomic_impl.h | 93 ++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/opal/include/opal/sys/atomic.h b/opal/include/opal/sys/atomic.h index 53e34333d8c..3b165f00e05 100644 --- a/opal/include/opal/sys/atomic.h +++ b/opal/include/opal/sys/atomic.h @@ -409,6 +409,10 @@ static inline int32_t opal_atomic_xor_fetch_32(volatile int32_t *addr, int32_t v static inline int32_t opal_atomic_fetch_xor_32(volatile int32_t *addr, int32_t value); static inline int32_t opal_atomic_sub_fetch_32(volatile int32_t *addr, int delta); static inline int32_t opal_atomic_fetch_sub_32(volatile int32_t *addr, int delta); +static inline int32_t opal_atomic_min_fetch_32 (volatile int32_t *addr, int32_t value); +static inline int32_t opal_atomic_fetch_min_32 (volatile int32_t *addr, int32_t value); +static inline int32_t opal_atomic_max_fetch_32 (volatile int32_t *addr, int32_t value); +static inline int32_t opal_atomic_fetch_max_32 (volatile int32_t *addr, int32_t value); #endif /* OPAL_HAVE_ATOMIC_MATH_32 */ @@ -434,8 +438,12 @@ static inline int64_t opal_atomic_fetch_or_64(volatile int64_t *addr, int64_t va static inline int64_t opal_atomic_fetch_xor_64(volatile int64_t *addr, int64_t value); static inline int64_t opal_atomic_sub_fetch_64(volatile int64_t *addr, int64_t delta); static inline int64_t opal_atomic_fetch_sub_64(volatile int64_t *addr, int64_t delta); +static inline int64_t opal_atomic_min_fetch_64 (volatile int64_t *addr, int64_t value); +static inline int64_t opal_atomic_fetch_min_64 (volatile int64_t *addr, int64_t value); +static inline int64_t opal_atomic_max_fetch_64 (volatile int64_t *addr, int64_t value); +static inline int64_t opal_atomic_fetch_max_64 (volatile int64_t *addr, int64_t value); -#endif /* OPAL_HAVE_ATOMIC_MATH_32 */ +#endif /* OPAL_HAVE_ATOMIC_MATH_64 */ #if ! OPAL_HAVE_ATOMIC_MATH_64 /* fix up the value of opal_have_atomic_math_64 to allow for C versions */ diff --git a/opal/include/opal/sys/atomic_impl.h b/opal/include/opal/sys/atomic_impl.h index a07e8c1897c..0eef41eb49a 100644 --- a/opal/include/opal/sys/atomic_impl.h +++ b/opal/include/opal/sys/atomic_impl.h @@ -39,6 +39,39 @@ *********************************************************************/ #if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_32 +#if !defined(OPAL_HAVE_ATOMIC_MIN_32) +static inline int32_t opal_atomic_fetch_min_32 (volatile int32_t *addr, int32_t value) +{ + int32_t old = *addr; + do { + if (old <= value) { + break; + } + } while (!opal_atomic_compare_exchange_strong_32 (addr, &old, value)); + + return old; +} + +#define OPAL_HAVE_ATOMIC_MIN_32 1 + +#endif /* OPAL_HAVE_ATOMIC_MIN_32 */ + +#if !defined(OPAL_HAVE_ATOMIC_MAX_32) +static inline int32_t opal_atomic_fetch_max_32 (volatile int32_t *addr, int32_t value) +{ + int32_t old = *addr; + do { + if (old >= value) { + break; + } + } while (!opal_atomic_compare_exchange_strong_32 (addr, &old, value)); + + return old; +} + +#define OPAL_HAVE_ATOMIC_MAX_32 1 +#endif /* OPAL_HAVE_ATOMIC_MAX_32 */ + #define OPAL_ATOMIC_DEFINE_CMPXCG_OP(type, bits, operation, name) \ static inline type opal_atomic_fetch_ ## name ## _ ## bits (volatile type *addr, type value) \ { \ @@ -104,6 +137,39 @@ OPAL_ATOMIC_DEFINE_CMPXCG_OP(int32_t, 32, -, sub) #if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_64 +#if !defined(OPAL_HAVE_ATOMIC_MIN_64) +static inline int64_t opal_atomic_fetch_min_64 (volatile int64_t *addr, int64_t value) +{ + int64_t old = *addr; + do { + if (old <= value) { + break; + } + } while (!opal_atomic_compare_exchange_strong_64 (addr, &old, value)); + + return old; +} + +#define OPAL_HAVE_ATOMIC_MIN_64 1 + +#endif /* OPAL_HAVE_ATOMIC_MIN_64 */ + +#if !defined(OPAL_HAVE_ATOMIC_MAX_64) +static inline int64_t opal_atomic_fetch_max_64 (volatile int64_t *addr, int64_t value) +{ + int64_t old = *addr; + do { + if (old >= value) { + break; + } + } while (!opal_atomic_compare_exchange_strong_64 (addr, &old, value)); + + return old; +} + +#define OPAL_HAVE_ATOMIC_MAX_64 1 +#endif /* OPAL_HAVE_ATOMIC_MAX_64 */ + #if !defined(OPAL_HAVE_ATOMIC_SWAP_64) #define OPAL_HAVE_ATOMIC_SWAP_64 1 static inline int64_t opal_atomic_swap_64(volatile int64_t *addr, @@ -115,7 +181,7 @@ static inline int64_t opal_atomic_swap_64(volatile int64_t *addr, return old; } -#endif /* OPAL_HAVE_ATOMIC_SWAP_32 */ +#endif /* OPAL_HAVE_ATOMIC_SWAP_64 */ #if !defined(OPAL_HAVE_ATOMIC_ADD_64) #define OPAL_HAVE_ATOMIC_ADD_64 1 @@ -321,12 +387,37 @@ OPAL_ATOMIC_DEFINE_OP_FETCH(or, |, int32_t, int32_t, 32) OPAL_ATOMIC_DEFINE_OP_FETCH(xor, ^, int32_t, int32_t, 32) OPAL_ATOMIC_DEFINE_OP_FETCH(sub, -, int32_t, int32_t, 32) +static inline int32_t opal_atomic_min_fetch_32 (volatile int32_t *addr, int32_t value) +{ + int32_t old = opal_atomic_fetch_min_32 (addr, value); + return old <= value ? old : value; +} + +static inline int32_t opal_atomic_max_fetch_32 (volatile int32_t *addr, int32_t value) +{ + int32_t old = opal_atomic_fetch_max_32 (addr, value); + return old >= value ? old : value; +} + #if OPAL_HAVE_ATOMIC_MATH_64 OPAL_ATOMIC_DEFINE_OP_FETCH(add, +, int64_t, int64_t, 64) OPAL_ATOMIC_DEFINE_OP_FETCH(and, &, int64_t, int64_t, 64) OPAL_ATOMIC_DEFINE_OP_FETCH(or, |, int64_t, int64_t, 64) OPAL_ATOMIC_DEFINE_OP_FETCH(xor, ^, int64_t, int64_t, 64) OPAL_ATOMIC_DEFINE_OP_FETCH(sub, -, int64_t, int64_t, 64) + +static inline int64_t opal_atomic_min_fetch_64 (volatile int64_t *addr, int64_t value) +{ + int64_t old = opal_atomic_fetch_min_64 (addr, value); + return old <= value ? old : value; +} + +static inline int64_t opal_atomic_max_fetch_64 (volatile int64_t *addr, int64_t value) +{ + int64_t old = opal_atomic_fetch_max_64 (addr, value); + return old >= value ? old : value; +} + #endif static inline intptr_t opal_atomic_fetch_add_ptr( volatile void* addr,