@@ -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
+
/**
* @}
*/
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 <ola.liljedahl@linaro.org> --- (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(-)