From 6f7cc553219676c71b83954e384b8071f6c144b9 Mon Sep 17 00:00:00 2001 From: Anders Roxell Date: Tue, 27 Jan 2015 19:41:51 +0100 Subject: api: atomic: move typedefs and inline functions Align the style with the rest of the header files of linux-generic Signed-off-by: Anders Roxell Reviewed-by: Balasubramanian Manoharan Reviewed-by: Taras Kondratiuk Signed-off-by: Maxim Uvarov --- include/odp/api/atomic.h | 209 +++------------------- platform/linux-generic/Makefile.am | 1 + platform/linux-generic/include/odp/atomic.h | 165 +++++++++++++++++ platform/linux-generic/include/odp/atomic_types.h | 78 ++++++++ 4 files changed, 267 insertions(+), 186 deletions(-) create mode 100644 platform/linux-generic/include/odp/atomic_types.h diff --git a/include/odp/api/atomic.h b/include/odp/api/atomic.h index ab424c096..93287499e 100644 --- a/include/odp/api/atomic.h +++ b/include/odp/api/atomic.h @@ -18,9 +18,6 @@ extern "C" { #endif -#include -#include - /** @addtogroup odp_synchronizers * Atomic types and relaxed operations. These operations cannot be used for * synchronization. @@ -28,29 +25,6 @@ extern "C" { */ -/** - * Atomic 64-bit unsigned integer - */ -typedef struct { - uint64_t v; /**< Actual storage for the atomic variable */ -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - /* Some architectures do not support lock-free operations on 64-bit - * data types. We use a spin lock to ensure atomicity. */ - char lock; /**< Spin lock (if needed) used to ensure atomic access */ -#endif -} odp_atomic_u64_t -ODP_ALIGNED(sizeof(uint64_t)); /* Enforce alignement! */ - - -/** - * Atomic 32-bit unsigned integer - */ -typedef struct { - uint32_t v; /**< Actual storage for the atomic variable */ -} odp_atomic_u32_t -ODP_ALIGNED(sizeof(uint32_t)); /* Enforce alignement! */ - - /** * Initialize atomic uint32 variable * @note Relaxed memory order, cannot be used for synchronization @@ -58,10 +32,8 @@ ODP_ALIGNED(sizeof(uint32_t)); /* Enforce alignement! */ * @param[out] atom Pointer to an atomic uint32 variable * @param val Value to initialize the variable with */ -static inline void odp_atomic_init_u32(odp_atomic_u32_t *atom, uint32_t val) -{ - __atomic_store_n(&atom->v, val, __ATOMIC_RELAXED); -} +void odp_atomic_init_u32(odp_atomic_u32_t *atom, uint32_t val); + /** * Load value of atomic uint32 variable @@ -71,10 +43,7 @@ static inline void odp_atomic_init_u32(odp_atomic_u32_t *atom, uint32_t val) * * @return Value of the variable */ -static inline uint32_t odp_atomic_load_u32(odp_atomic_u32_t *atom) -{ - return __atomic_load_n(&atom->v, __ATOMIC_RELAXED); -} +uint32_t odp_atomic_load_u32(odp_atomic_u32_t *atom); /** * Store value to atomic uint32 variable @@ -83,11 +52,7 @@ static inline uint32_t odp_atomic_load_u32(odp_atomic_u32_t *atom) * @param[out] atom Pointer to an atomic uint32 variable * @param val Value to store in the variable */ -static inline void odp_atomic_store_u32(odp_atomic_u32_t *atom, - uint32_t val) -{ - __atomic_store_n(&atom->v, val, __ATOMIC_RELAXED); -} +void odp_atomic_store_u32(odp_atomic_u32_t *atom, uint32_t val); /** * Fetch and add to atomic uint32 variable @@ -98,11 +63,7 @@ static inline void odp_atomic_store_u32(odp_atomic_u32_t *atom, * * @return Value of the variable before the addition */ -static inline uint32_t odp_atomic_fetch_add_u32(odp_atomic_u32_t *atom, - uint32_t val) -{ - return __atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED); -} +uint32_t odp_atomic_fetch_add_u32(odp_atomic_u32_t *atom, uint32_t val); /** * Add to atomic uint32 variable @@ -111,11 +72,7 @@ static inline uint32_t odp_atomic_fetch_add_u32(odp_atomic_u32_t *atom, * @param[in,out] atom Pointer to an atomic uint32 variable * @param val A value to be added to the variable */ -static inline void odp_atomic_add_u32(odp_atomic_u32_t *atom, - uint32_t val) -{ - (void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED); -} +void odp_atomic_add_u32(odp_atomic_u32_t *atom, uint32_t val); /** * Fetch and subtract from atomic uint32 variable @@ -126,11 +83,7 @@ static inline void odp_atomic_add_u32(odp_atomic_u32_t *atom, * * @return Value of the variable before the subtraction */ -static inline uint32_t odp_atomic_fetch_sub_u32(odp_atomic_u32_t *atom, - uint32_t val) -{ - return __atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED); -} +uint32_t odp_atomic_fetch_sub_u32(odp_atomic_u32_t *atom, uint32_t val); /** * Subtract from atomic uint32 variable @@ -139,11 +92,7 @@ static inline uint32_t odp_atomic_fetch_sub_u32(odp_atomic_u32_t *atom, * @param[in,out] atom Pointer to an atomic uint32 variable * @param val Value to be subtracted from the variable */ -static inline void odp_atomic_sub_u32(odp_atomic_u32_t *atom, - uint32_t val) -{ - (void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED); -} +void odp_atomic_sub_u32(odp_atomic_u32_t *atom, uint32_t val); /** * Fetch and increment atomic uint32 variable @@ -154,10 +103,7 @@ static inline void odp_atomic_sub_u32(odp_atomic_u32_t *atom, * @return Value of the variable before the increment */ -static inline uint32_t odp_atomic_fetch_inc_u32(odp_atomic_u32_t *atom) -{ - return __atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED); -} +uint32_t odp_atomic_fetch_inc_u32(odp_atomic_u32_t *atom); /** * Increment atomic uint32 variable @@ -165,10 +111,7 @@ static inline uint32_t odp_atomic_fetch_inc_u32(odp_atomic_u32_t *atom) * * @param[in,out] atom Pointer to an atomic uint32 variable */ -static inline void odp_atomic_inc_u32(odp_atomic_u32_t *atom) -{ - (void)__atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED); -} +void odp_atomic_inc_u32(odp_atomic_u32_t *atom); /** * Fetch and decrement atomic uint32 variable @@ -178,10 +121,7 @@ static inline void odp_atomic_inc_u32(odp_atomic_u32_t *atom) * * @return Value of the variable before the subtraction */ -static inline uint32_t odp_atomic_fetch_dec_u32(odp_atomic_u32_t *atom) -{ - return __atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED); -} +uint32_t odp_atomic_fetch_dec_u32(odp_atomic_u32_t *atom); /** * Decrement atomic uint32 variable @@ -189,10 +129,7 @@ static inline uint32_t odp_atomic_fetch_dec_u32(odp_atomic_u32_t *atom) * * @param[in,out] atom Pointer to an atomic uint32 variable */ -static inline void odp_atomic_dec_u32(odp_atomic_u32_t *atom) -{ - (void)__atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED); -} +void odp_atomic_dec_u32(odp_atomic_u32_t *atom); /** * Initialize atomic uint64 variable @@ -201,34 +138,7 @@ static inline void odp_atomic_dec_u32(odp_atomic_u32_t *atom) * @param[out] atom Pointer to an atomic uint64 variable * @param val Value to initialize the variable with */ -static inline void odp_atomic_init_u64(odp_atomic_u64_t *atom, uint64_t val) -{ - atom->v = val; -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - __atomic_clear(&atom->lock, __ATOMIC_RELAXED); -#endif -} - -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 -/** - * @internal - * Helper macro for lock-based atomic operations on 64-bit integers - * @param[in,out] atom Pointer to the 64-bit atomic variable - * @param expr Expression used update the variable. - * @return The old value of the variable. - */ -#define ATOMIC_OP(atom, expr) \ -({ \ - uint64_t old_val; \ - /* Loop while lock is already taken, stop when lock becomes clear */ \ - while (__atomic_test_and_set(&(atom)->lock, __ATOMIC_ACQUIRE)) \ - (void)0; \ - old_val = (atom)->v; \ - (expr); /* Perform whatever update is desired */ \ - __atomic_clear(&(atom)->lock, __ATOMIC_RELEASE); \ - old_val; /* Return old value */ \ -}) -#endif +void odp_atomic_init_u64(odp_atomic_u64_t *atom, uint64_t val); /** * Load value of atomic uint64 variable @@ -238,14 +148,7 @@ static inline void odp_atomic_init_u64(odp_atomic_u64_t *atom, uint64_t val) * * @return Value of the variable */ -static inline uint64_t odp_atomic_load_u64(odp_atomic_u64_t *atom) -{ -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - return ATOMIC_OP(atom, (void)0); -#else - return __atomic_load_n(&atom->v, __ATOMIC_RELAXED); -#endif -} +uint64_t odp_atomic_load_u64(odp_atomic_u64_t *atom); /** * Store value to atomic uint64 variable @@ -254,15 +157,7 @@ static inline uint64_t odp_atomic_load_u64(odp_atomic_u64_t *atom) * @param[out] atom Pointer to an atomic uint64 variable * @param val Value to store in the variable */ -static inline void odp_atomic_store_u64(odp_atomic_u64_t *atom, - uint64_t val) -{ -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - (void)ATOMIC_OP(atom, atom->v = val); -#else - __atomic_store_n(&atom->v, val, __ATOMIC_RELAXED); -#endif -} +void odp_atomic_store_u64(odp_atomic_u64_t *atom, uint64_t val); /** * Fetch and add to atomic uint64 variable @@ -274,15 +169,7 @@ static inline void odp_atomic_store_u64(odp_atomic_u64_t *atom, * @return Value of the variable before the addition */ -static inline uint64_t odp_atomic_fetch_add_u64(odp_atomic_u64_t *atom, - uint64_t val) -{ -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - return ATOMIC_OP(atom, atom->v += val); -#else - return __atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED); -#endif -} +uint64_t odp_atomic_fetch_add_u64(odp_atomic_u64_t *atom, uint64_t val); /** * Add to atomic uint64 variable @@ -292,14 +179,7 @@ static inline uint64_t odp_atomic_fetch_add_u64(odp_atomic_u64_t *atom, * @param val Value to be added to the variable * */ -static inline void odp_atomic_add_u64(odp_atomic_u64_t *atom, uint64_t val) -{ -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - (void)ATOMIC_OP(atom, atom->v += val); -#else - (void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED); -#endif -} +void odp_atomic_add_u64(odp_atomic_u64_t *atom, uint64_t val); /** * Fetch and subtract from atomic uint64 variable @@ -310,15 +190,7 @@ static inline void odp_atomic_add_u64(odp_atomic_u64_t *atom, uint64_t val) * * @return Value of the variable before the subtraction */ -static inline uint64_t odp_atomic_fetch_sub_u64(odp_atomic_u64_t *atom, - uint64_t val) -{ -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - return ATOMIC_OP(atom, atom->v -= val); -#else - return __atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED); -#endif -} +uint64_t odp_atomic_fetch_sub_u64(odp_atomic_u64_t *atom, uint64_t val); /** * Subtract from atomic uint64 variable @@ -327,14 +199,7 @@ static inline uint64_t odp_atomic_fetch_sub_u64(odp_atomic_u64_t *atom, * @param[in,out] atom Pointer to an atomic uint64 variable * @param val Value to be subtracted from the variable */ -static inline void odp_atomic_sub_u64(odp_atomic_u64_t *atom, uint64_t val) -{ -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - (void)ATOMIC_OP(atom, atom->v -= val); -#else - (void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED); -#endif -} +void odp_atomic_sub_u64(odp_atomic_u64_t *atom, uint64_t val); /** * Fetch and increment atomic uint64 variable @@ -344,14 +209,7 @@ static inline void odp_atomic_sub_u64(odp_atomic_u64_t *atom, uint64_t val) * * @return Value of the variable before the increment */ -static inline uint64_t odp_atomic_fetch_inc_u64(odp_atomic_u64_t *atom) -{ -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - return ATOMIC_OP(atom, atom->v++); -#else - return __atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED); -#endif -} +uint64_t odp_atomic_fetch_inc_u64(odp_atomic_u64_t *atom); /** * Increment atomic uint64 variable @@ -359,14 +217,7 @@ static inline uint64_t odp_atomic_fetch_inc_u64(odp_atomic_u64_t *atom) * * @param[in,out] atom Pointer to an atomic uint64 variable */ -static inline void odp_atomic_inc_u64(odp_atomic_u64_t *atom) -{ -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - (void)ATOMIC_OP(atom, atom->v++); -#else - (void)__atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED); -#endif -} +void odp_atomic_inc_u64(odp_atomic_u64_t *atom); /** * Fetch and decrement atomic uint64 variable @@ -376,14 +227,7 @@ static inline void odp_atomic_inc_u64(odp_atomic_u64_t *atom) * * @return Value of the variable before the decrement */ -static inline uint64_t odp_atomic_fetch_dec_u64(odp_atomic_u64_t *atom) -{ -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - return ATOMIC_OP(atom, atom->v--); -#else - return __atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED); -#endif -} +uint64_t odp_atomic_fetch_dec_u64(odp_atomic_u64_t *atom); /** * Decrement atomic uint64 variable @@ -391,14 +235,7 @@ static inline uint64_t odp_atomic_fetch_dec_u64(odp_atomic_u64_t *atom) * * @param[in,out] atom Pointer to an atomic uint64 variable */ -static inline void odp_atomic_dec_u64(odp_atomic_u64_t *atom) -{ -#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 - (void)ATOMIC_OP(atom, atom->v--); -#else - (void)__atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED); -#endif -} +void odp_atomic_dec_u64(odp_atomic_u64_t *atom); /** * @} diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index d07dbaa5a..f8a313322 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -12,6 +12,7 @@ odpincludedir= $(includedir)/odp odpinclude_HEADERS = \ $(top_srcdir)/platform/linux-generic/include/odp/align.h \ $(top_srcdir)/platform/linux-generic/include/odp/atomic.h \ + $(top_srcdir)/platform/linux-generic/include/odp/atomic_types.h \ $(top_srcdir)/platform/linux-generic/include/odp/barrier.h \ $(top_srcdir)/platform/linux-generic/include/odp/buffer.h \ $(top_srcdir)/platform/linux-generic/include/odp/pool.h \ diff --git a/platform/linux-generic/include/odp/atomic.h b/platform/linux-generic/include/odp/atomic.h index f39ef2a81..952b0f4a0 100644 --- a/platform/linux-generic/include/odp/atomic.h +++ b/platform/linux-generic/include/odp/atomic.h @@ -17,10 +17,175 @@ extern "C" { #endif +#include +#include +#include + /** @ingroup odp_synchronizers * @{ */ +static inline void odp_atomic_init_u32(odp_atomic_u32_t *atom, uint32_t val) +{ + __atomic_store_n(&atom->v, val, __ATOMIC_RELAXED); +} + +static inline uint32_t odp_atomic_load_u32(odp_atomic_u32_t *atom) +{ + return __atomic_load_n(&atom->v, __ATOMIC_RELAXED); +} + +static inline void odp_atomic_store_u32(odp_atomic_u32_t *atom, + uint32_t val) +{ + __atomic_store_n(&atom->v, val, __ATOMIC_RELAXED); +} + +static inline uint32_t odp_atomic_fetch_add_u32(odp_atomic_u32_t *atom, + uint32_t val) +{ + return __atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED); +} + +static inline void odp_atomic_add_u32(odp_atomic_u32_t *atom, + uint32_t val) +{ + (void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED); +} + +static inline uint32_t odp_atomic_fetch_sub_u32(odp_atomic_u32_t *atom, + uint32_t val) +{ + return __atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED); +} + +static inline void odp_atomic_sub_u32(odp_atomic_u32_t *atom, + uint32_t val) +{ + (void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED); +} + +static inline uint32_t odp_atomic_fetch_inc_u32(odp_atomic_u32_t *atom) +{ + return __atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED); +} + +static inline void odp_atomic_inc_u32(odp_atomic_u32_t *atom) +{ + (void)__atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED); +} + +static inline uint32_t odp_atomic_fetch_dec_u32(odp_atomic_u32_t *atom) +{ + return __atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED); +} + +static inline void odp_atomic_dec_u32(odp_atomic_u32_t *atom) +{ + (void)__atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED); +} + +static inline void odp_atomic_init_u64(odp_atomic_u64_t *atom, uint64_t val) +{ + atom->v = val; +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + __atomic_clear(&atom->lock, __ATOMIC_RELAXED); +#endif +} + +static inline uint64_t odp_atomic_load_u64(odp_atomic_u64_t *atom) +{ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + return ATOMIC_OP(atom, (void)0); +#else + return __atomic_load_n(&atom->v, __ATOMIC_RELAXED); +#endif +} + +static inline void odp_atomic_store_u64(odp_atomic_u64_t *atom, + uint64_t val) +{ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + (void)ATOMIC_OP(atom, atom->v = val); +#else + __atomic_store_n(&atom->v, val, __ATOMIC_RELAXED); +#endif +} + +static inline uint64_t odp_atomic_fetch_add_u64(odp_atomic_u64_t *atom, + uint64_t val) +{ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + return ATOMIC_OP(atom, atom->v += val); +#else + return __atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED); +#endif +} + +static inline void odp_atomic_add_u64(odp_atomic_u64_t *atom, uint64_t val) +{ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + (void)ATOMIC_OP(atom, atom->v += val); +#else + (void)__atomic_fetch_add(&atom->v, val, __ATOMIC_RELAXED); +#endif +} + +static inline uint64_t odp_atomic_fetch_sub_u64(odp_atomic_u64_t *atom, + uint64_t val) +{ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + return ATOMIC_OP(atom, atom->v -= val); +#else + return __atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED); +#endif +} + +static inline void odp_atomic_sub_u64(odp_atomic_u64_t *atom, uint64_t val) +{ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + (void)ATOMIC_OP(atom, atom->v -= val); +#else + (void)__atomic_fetch_sub(&atom->v, val, __ATOMIC_RELAXED); +#endif +} + +static inline uint64_t odp_atomic_fetch_inc_u64(odp_atomic_u64_t *atom) +{ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + return ATOMIC_OP(atom, atom->v++); +#else + return __atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED); +#endif +} + +static inline void odp_atomic_inc_u64(odp_atomic_u64_t *atom) +{ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + (void)ATOMIC_OP(atom, atom->v++); +#else + (void)__atomic_fetch_add(&atom->v, 1, __ATOMIC_RELAXED); +#endif +} + +static inline uint64_t odp_atomic_fetch_dec_u64(odp_atomic_u64_t *atom) +{ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + return ATOMIC_OP(atom, atom->v--); +#else + return __atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED); +#endif +} + +static inline void odp_atomic_dec_u64(odp_atomic_u64_t *atom) +{ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + (void)ATOMIC_OP(atom, atom->v--); +#else + (void)__atomic_fetch_sub(&atom->v, 1, __ATOMIC_RELAXED); +#endif +} + /** * @} */ diff --git a/platform/linux-generic/include/odp/atomic_types.h b/platform/linux-generic/include/odp/atomic_types.h new file mode 100644 index 000000000..69a50c927 --- /dev/null +++ b/platform/linux-generic/include/odp/atomic_types.h @@ -0,0 +1,78 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/** + * @file + * + * ODP atomic operations + */ + +#ifndef ODP_ATOMIC_TYPES_H_ +#define ODP_ATOMIC_TYPES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup odp_synchronizers + * Atomic types and relaxed operations. These operations cannot be used for + * synchronization. + * @{ + */ + +/** + * Atomic 64-bit unsigned integer + */ +typedef struct { + uint64_t v; /**< Actual storage for the atomic variable */ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + /* Some architectures do not support lock-free operations on 64-bit + * data types. We use a spin lock to ensure atomicity. */ + char lock; /**< Spin lock (if needed) used to ensure atomic access */ +#endif +} odp_atomic_u64_t +ODP_ALIGNED(sizeof(uint64_t)); /* Enforce alignement! */ + + +/** + * Atomic 32-bit unsigned integer + */ +typedef struct { + uint32_t v; /**< Actual storage for the atomic variable */ +} odp_atomic_u32_t +ODP_ALIGNED(sizeof(uint32_t)); /* Enforce alignement! */ + +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 +/** + * @internal + * Helper macro for lock-based atomic operations on 64-bit integers + * @param[in,out] atom Pointer to the 64-bit atomic variable + * @param expr Expression used update the variable. + * @return The old value of the variable. + */ +#define ATOMIC_OP(atom, expr) \ +({ \ + uint64_t old_val; \ + /* Loop while lock is already taken, stop when lock becomes clear */ \ + while (__atomic_test_and_set(&(atom)->lock, __ATOMIC_ACQUIRE)) \ + (void)0; \ + old_val = (atom)->v; \ + (expr); /* Perform whatever update is desired */ \ + __atomic_clear(&(atom)->lock, __ATOMIC_RELEASE); \ + old_val; /* Return old value */ \ +}) +#endif + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif -- cgit v1.2.3