Limited support (swap, cas) for 128-bit atomic types and operations, conditionally enabled if and when the compiler supports it. Changed some return types from int to odp_bool_t to better match the semantics of the returned values.
Signed-off-by: Ola Liljedahl <[email protected]> --- (This document/code contribution attached is provided under the terms of agreement LES-LTM-21309) This is actually v2 of patch 1/2 from 2014-12-01. Patch 2/2 became the separate timer patch set. The 128-bit atomics support is optionally needed by the new lock-less timer implementation. .../linux-generic/include/odp_atomic_internal.h | 73 +++++++++++++++++++--- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/platform/linux-generic/include/odp_atomic_internal.h b/platform/linux-generic/include/odp_atomic_internal.h index dafa222..91d2c3e 100644 --- a/platform/linux-generic/include/odp_atomic_internal.h +++ b/platform/linux-generic/include/odp_atomic_internal.h @@ -146,7 +146,7 @@ static inline uint32_t _odp_atomic_u32_xchg_mm(odp_atomic_u32_t *atom, * @retval 1 exchange successul * @retval 0 exchange failed and '*exp' updated with current value */ -static inline int _odp_atomic_u32_cmp_xchg_strong_mm( +static inline odp_bool_t _odp_atomic_u32_cmp_xchg_strong_mm( odp_atomic_u32_t *atom, uint32_t *exp, uint32_t val, @@ -304,7 +304,6 @@ static inline void _odp_atomic_u64_store_mm(odp_atomic_u64_t *atom, static inline uint64_t _odp_atomic_u64_xchg_mm(odp_atomic_u64_t *atom, uint64_t val, _odp_memmodel_t mmodel) - { #if !defined __GCC_ATOMIC_LLONG_LOCK_FREE || __GCC_ATOMIC_LLONG_LOCK_FREE < 2 return ATOMIC_OP_MM(atom, atom->v = val, mmodel); @@ -328,7 +327,8 @@ static inline uint64_t _odp_atomic_u64_xchg_mm(odp_atomic_u64_t *atom, * @retval 1 exchange successful * @retval 0 exchange failed and '*exp' updated with current value */ -static inline int _odp_atomic_u64_cmp_xchg_strong_mm(odp_atomic_u64_t *atom, +static inline +odp_bool_t _odp_atomic_u64_cmp_xchg_strong_mm(odp_atomic_u64_t *atom, uint64_t *exp, uint64_t val, _odp_memmodel_t success, @@ -389,7 +389,6 @@ static inline uint64_t _odp_atomic_u64_fetch_add_mm(odp_atomic_u64_t *atom, static inline void _odp_atomic_u64_add_mm(odp_atomic_u64_t *atom, uint64_t val, _odp_memmodel_t mmodel) - { #if !defined __GCC_ATOMIC_LLONG_LOCK_FREE || __GCC_ATOMIC_LLONG_LOCK_FREE < 2 (void)ATOMIC_OP_MM(atom, atom->v += val, mmodel); @@ -428,7 +427,6 @@ static inline uint64_t _odp_atomic_u64_fetch_sub_mm(odp_atomic_u64_t *atom, static inline void _odp_atomic_u64_sub_mm(odp_atomic_u64_t *atom, uint64_t val, _odp_memmodel_t mmodel) - { #if !defined __GCC_ATOMIC_LLONG_LOCK_FREE || __GCC_ATOMIC_LLONG_LOCK_FREE < 2 (void)ATOMIC_OP_MM(atom, atom->v -= val, mmodel); @@ -519,7 +517,7 @@ static inline void *_odp_atomic_ptr_xchg(_odp_atomic_ptr_t *atom, * @retval 1 exchange successful * @retval 0 exchange failed and '*exp' updated with current value */ -static inline int _odp_atomic_ptr_cmp_xchg_strong( +static inline odp_bool_t _odp_atomic_ptr_cmp_xchg_strong( _odp_atomic_ptr_t *atom, void **exp, void *val, @@ -542,7 +540,7 @@ static inline int _odp_atomic_ptr_cmp_xchg_strong( *****************************************************************************/ /** - * Initialize a flag atomic variable + * Initialize an atomic flag variable * * @param[out] flag Pointer to a flag atomic variable * @param val The initial value of the variable @@ -570,7 +568,8 @@ static inline int _odp_atomic_flag_load(_odp_atomic_flag_t *flag) /** * Test-and-set of atomic flag variable * @Note Operation has acquire semantics. It pairs with a later - * release operation. + * release operation in some thread. It does not provide release or + * acquire/release semantics. * * @param[in,out] flag Pointer to a flag atomic variable * @@ -595,6 +594,64 @@ static inline void _odp_atomic_flag_clear(_odp_atomic_flag_t *flag) __atomic_clear(flag, __ATOMIC_RELEASE); } +/* Check if target and compiler supports 128-bit scalars and corresponding + * exchange and CAS operations */ +/* GCC on x86-64 needs -mcx16 compiler option */ +#if defined __SIZEOF_INT128__ && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 + +/** Preprocessor symbol that indicates support for 128-bit atomics */ +#define ODP_ATOMIC_U128 + +/** An unsigned 128-bit (16-byte) scalar type */ +typedef __int128 _uint128_t; + +/** Atomic 128-bit type */ +typedef struct { + _uint128_t v; /**< Actual storage for the atomic variable */ +} _odp_atomic_u128_t ODP_ALIGNED(16); + +/** + * 16-byte atomic exchange operation + * + * @param ptr Pointer to a 16-byte atomic variable + * @param val Pointer to new value to write + * @param old Pointer to location for old value + * @param mmodel Memory model associated with the exchange operation + */ +static inline void _odp_atomic_u128_xchg_mm(_odp_atomic_u128_t *ptr, + _uint128_t *val, + _uint128_t *old, + _odp_memmodel_t mm) +{ + __atomic_exchange(&ptr->v, val, old, mm); +} + +/** + * Atomic compare and exchange (swap) of 16-byte atomic variable + * "Strong" semantics, will not fail spuriously. + * + * @param ptr Pointer to a 16-byte atomic variable + * @param exp Pointer to expected value (updated on failure) + * @param val Pointer to new value to write + * @param succ Memory model associated with a successful compare-and-swap + * operation + * @param fail Memory model associated with a failed compare-and-swap + * operation + * + * @retval 1 exchange successul + * @retval 0 exchange failed and '*exp' updated with current value + */ +static inline odp_bool_t _odp_atomic_u128_cmp_xchg_mm(_odp_atomic_u128_t *ptr, + _uint128_t *exp, + _uint128_t *val, + _odp_memmodel_t succ, + _odp_memmodel_t fail) +{ + return __atomic_compare_exchange(&ptr->v, exp, val, + false/*strong*/, succ, fail); +} +#endif + /** * @} */ -- 1.9.1 _______________________________________________ lng-odp mailing list [email protected] http://lists.linaro.org/mailman/listinfo/lng-odp
