eal/x86: add 128-bit atomic compare exchange

This operation can be used for non-blocking algorithms, such as a
non-blocking stack or ring.

It is available only for x86_64.

Signed-off-by: Gage Eads <gage.eads@intel.com>
Reviewed-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>
This commit is contained in:
Gage Eads 2019-04-03 14:44:56 -05:00 committed by Thomas Monjalon
parent 3f9aab961e
commit 640c5f09ef
2 changed files with 99 additions and 0 deletions

View File

@ -34,6 +34,7 @@
/*
* Inspired from FreeBSD src/sys/amd64/include/atomic.h
* Copyright (c) 1998 Doug Rabson
* Copyright (c) 2019 Intel Corporation
* All rights reserved.
*/
@ -46,6 +47,7 @@
#include <stdint.h>
#include <rte_common.h>
#include <rte_compat.h>
#include <rte_atomic.h>
/*------------------------- 64 bit atomic operations -------------------------*/
@ -208,4 +210,49 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v)
}
#endif
/*------------------------ 128 bit atomic operations -------------------------*/
/**
* 128-bit integer structure.
*/
RTE_STD_C11
typedef struct {
RTE_STD_C11
union {
uint64_t val[2];
__int128 int128;
};
} __rte_aligned(16) rte_int128_t;
static inline int __rte_experimental
rte_atomic128_cmp_exchange(rte_int128_t *dst,
rte_int128_t *exp,
const rte_int128_t *src,
unsigned int weak,
int success,
int failure)
{
RTE_SET_USED(weak);
RTE_SET_USED(success);
RTE_SET_USED(failure);
uint8_t res;
asm volatile (
MPLOCKED
"cmpxchg16b %[dst];"
" sete %[res]"
: [dst] "=m" (dst->val[0]),
"=a" (exp->val[0]),
"=d" (exp->val[1]),
[res] "=r" (res)
: "b" (src->val[0]),
"c" (src->val[1]),
"a" (exp->val[0]),
"d" (exp->val[1]),
"m" (dst->val[0])
: "memory");
return res;
}
#endif /* _RTE_ATOMIC_X86_64_H_ */

View File

@ -1079,4 +1079,56 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v)
}
#endif
/*------------------------ 128 bit atomic operations -------------------------*/
#ifdef __DOXYGEN__
/**
* An atomic compare and set function used by the mutex functions.
* (Atomically) Equivalent to:
* @code
* if (*dst == *exp)
* *dst = *src
* else
* *exp = *dst
* @endcode
*
* @note This function is currently only available for the x86-64 platform.
*
* @note The success and failure arguments must be one of the __ATOMIC_* values
* defined in the C++11 standard. For details on their behavior, refer to the
* standard.
*
* @param dst
* The destination into which the value will be written.
* @param exp
* Pointer to the expected value. If the operation fails, this memory is
* updated with the actual value.
* @param src
* Pointer to the new value.
* @param weak
* A value of true allows the comparison to spuriously fail and allows the
* 'exp' update to occur non-atomically (i.e. a torn read may occur).
* Implementations may ignore this argument and only implement the strong
* variant.
* @param success
* If successful, the operation's memory behavior conforms to this (or a
* stronger) model.
* @param failure
* If unsuccessful, the operation's memory behavior conforms to this (or a
* stronger) model. This argument cannot be __ATOMIC_RELEASE,
* __ATOMIC_ACQ_REL, or a stronger model than success.
* @return
* Non-zero on success; 0 on failure.
*/
static inline int __rte_experimental
rte_atomic128_cmp_exchange(rte_int128_t *dst,
rte_int128_t *exp,
const rte_int128_t *src,
unsigned int weak,
int success,
int failure);
#endif /* __DOXYGEN__ */
#endif /* _RTE_ATOMIC_H_ */