Added 32 bit acquire load/cas and release store/add/sub calls. These are the minimum set of non-relaxed calls that are needed for building lock-free algorithms. 64 bit versions can be added later.
Signed-off-by: Petri Savolainen <petri.savolai...@nokia.com> --- include/odp/api/atomic.h | 80 ++++++++++++++++++++++++++++- platform/linux-generic/include/odp/atomic.h | 32 ++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/include/odp/api/atomic.h b/include/odp/api/atomic.h index b79a50a..316f13a 100644 --- a/include/odp/api/atomic.h +++ b/include/odp/api/atomic.h @@ -21,7 +21,7 @@ extern "C" { /** * @defgroup odp_atomic ODP ATOMIC * @details - * <b> Atomic integers </b> + * <b> Atomic integers using relaxed memory ordering </b> * * Atomic integer types (odp_atomic_u32_t and odp_atomic_u64_t) can be used to * implement e.g. shared counters. If not otherwise documented, operations in @@ -31,6 +31,18 @@ extern "C" { * before or after the operation), only atomicity of the operation itself is * guaranteed. * + * <b> Operations with other than relaxed memory ordering </b> + * + * <b> An operation with RELEASE </b> memory ordering (odp_atomic_xxx_rls_xxx()) + * ensures that other threads loading the same atomic variable with ACQUIRE + * memory ordering see all stores (from the calling thread) that happened before + * this releasing store. + * + * <b> An operation with ACQUIRE </b> memory ordering (odp_atomic_xxx_acq_xxx()) + * ensures that the calling thread sees all stores (done by the releasing + * thread) that happened before a RELEASE memory ordered store to the same + * atomic variable. + * * @{ */ @@ -309,6 +321,72 @@ void odp_atomic_min_u64(odp_atomic_u64_t *atom, uint64_t new_min); int odp_atomic_cas_u64(odp_atomic_u64_t *atom, uint64_t *old_val, uint64_t new_val); +/* + * Operations with other than relaxed memory ordering + * -------------------------------------------------- + */ + +/** + * Load value of atomic uint32 variable using ACQUIRE memory ordering + * + * Otherwise identical to odp_atomic_load_u32() but ensures ACQUIRE memory + * ordering. + * + * @param atom Pointer to atomic variable + * + * @return Value of the variable + */ +uint32_t odp_atomic_load_acq_u32(odp_atomic_u32_t *atom); + +/** + * Compare and swap atomic uint32 variable using ACQUIRE memory ordering + * + * Otherwise identical to odp_atomic_cas_u32() but ensures ACQUIRE memory + * ordering. + * + * @param atom Pointer to atomic variable + * @param[in,out] old_val Pointer to the old value of the atomic variable. + * Operation updates this value on failure. + * @param new_val New value to be written into the atomic variable + * + * @return 0 on failure, !0 on success + */ +int odp_atomic_cas_acq_u32(odp_atomic_u32_t *atom, uint32_t *old_val, + uint32_t new_val); + +/** + * Store value to atomic uint32 variable using RELEASE memory ordering + * + * Otherwise identical to odp_atomic_store_u32() but ensures RELEASE memory + * ordering. + * + * @param atom Pointer to atomic variable + * @param val Value to store in the variable + */ +void odp_atomic_store_rls_u32(odp_atomic_u32_t *atom, uint32_t val); + +/** + * Add to atomic uint32 variable using RELEASE memory ordering + * + * Otherwise identical to odp_atomic_add_u32() but ensures RELEASE memory + * ordering. + * + * @param atom Pointer to atomic variable + * @param val Value to be added to the variable + */ +void odp_atomic_add_rls_u32(odp_atomic_u32_t *atom, uint32_t val); + +/** + * Subtract from atomic uint32 variable using RELEASE memory ordering + * + * Otherwise identical to odp_atomic_sub_u32() but ensures RELEASE memory + * ordering. + * + * @param atom Pointer to atomic variable + * @param val Value to be subtracted from the variable + */ +void odp_atomic_sub_rls_u32(odp_atomic_u32_t *atom, uint32_t val); + /** * @} */ diff --git a/platform/linux-generic/include/odp/atomic.h b/platform/linux-generic/include/odp/atomic.h index b2bc5c4..005a0cd 100644 --- a/platform/linux-generic/include/odp/atomic.h +++ b/platform/linux-generic/include/odp/atomic.h @@ -258,6 +258,38 @@ static inline void odp_atomic_min_u64(odp_atomic_u64_t *atom, uint64_t new_min) } } +static inline uint32_t odp_atomic_load_acq_u32(odp_atomic_u32_t *atom) +{ + return __atomic_load_n(&atom->v, __ATOMIC_ACQUIRE); +} + +static inline int odp_atomic_cas_acq_u32(odp_atomic_u32_t *atom, + uint32_t *old_val, uint32_t new_val) +{ + return __atomic_compare_exchange_n(&atom->v, old_val, new_val, + 0 /* strong */, + __ATOMIC_ACQUIRE, + __ATOMIC_RELAXED); +} + +static inline void odp_atomic_store_rls_u32(odp_atomic_u32_t *atom, + uint32_t val) +{ + __atomic_store_n(&atom->v, val, __ATOMIC_RELEASE); +} + +static inline void odp_atomic_add_rls_u32(odp_atomic_u32_t *atom, + uint32_t val) +{ + (void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELEASE); +} + +static inline void odp_atomic_sub_rls_u32(odp_atomic_u32_t *atom, + uint32_t val) +{ + (void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELEASE); +} + /** * @} */ -- 2.6.2 _______________________________________________ lng-odp mailing list lng-odp@lists.linaro.org https://lists.linaro.org/mailman/listinfo/lng-odp