Platforms may support some uint64 operations lock-free and others not. For example, inc_64 can be natively supported but cas_64 (or max_64/min_64) not. User may be able to switch to 32 bit variables when a 64 bit operation uses locks. The same atomic operation struture could be used for platform init to guide lock vs. lock-free implementation (e.g. if cas_64 is never called, inc_64 can be lock-free).
Signed-off-by: Petri Savolainen <petri.savolai...@nokia.com> --- include/odp/api/atomic.h | 48 +++++++++++++++++++++++++++++++++++++ platform/linux-generic/Makefile.am | 1 + platform/linux-generic/odp_atomic.c | 24 +++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 platform/linux-generic/odp_atomic.c diff --git a/include/odp/api/atomic.h b/include/odp/api/atomic.h index 316f13a..5e897c1 100644 --- a/include/odp/api/atomic.h +++ b/include/odp/api/atomic.h @@ -388,6 +388,54 @@ void odp_atomic_add_rls_u32(odp_atomic_u32_t *atom, uint32_t val); void odp_atomic_sub_rls_u32(odp_atomic_u32_t *atom, uint32_t val); /** + * Atomic operations + * + * Atomic operations listed in a bit field structure. + */ +typedef union odp_atomic_op_t { + /** Operation flags */ + struct { + uint32_t init : 1; /**< Init atomic variable */ + uint32_t load : 1; /**< Atomic load */ + uint32_t store : 1; /**< Atomic store */ + uint32_t fetch_add : 1; /**< Atomic fetch and add */ + uint32_t add : 1; /**< Atomic add */ + uint32_t fetch_sub : 1; /**< Atomic fetch and substract */ + uint32_t sub : 1; /**< Atomic substract */ + uint32_t fetch_inc : 1; /**< Atomic fetch and increment */ + uint32_t inc : 1; /**< Atomic increment */ + uint32_t fetch_dec : 1; /**< Atomic fetch and decrement */ + uint32_t dec : 1; /**< Atomic decrement */ + uint32_t min : 1; /**< Atomic minimum */ + uint32_t max : 1; /**< Atomic maximum */ + uint32_t cas : 1; /**< Atomic compare and swap */ + } op; + + /** All bits of the bit field structure. + * Operation flag mapping is architecture specific. This field can be + * used to set/clear all flags, or bitwise operations over the entire + * structure. */ + uint32_t all_bits; +} odp_atomic_op_t; + +/** + * Query which atomic uint64 operations are lock-free + * + * Lock-free implementations have higher performance and scale better than + * implementations using locks. User can decide to use e.g. uint32 atomic + * variables instead of uint64 to optimize performance on platforms that + * implement a performance critical operation using locks. + * + * @param atomic_op Pointer to atomic operation structure for storing + * operation flags. All bits are initialized to zero during + * the operation. The parameter is ignored when NULL. + * @retval 0 None of the operations are lock-free + * @retval 1 Some of the operations are lock-free + * @retval 2 All operations are lock-free + */ +int odp_atomic_lock_free_u64(odp_atomic_op_t *atomic_op); + +/** * @} */ diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index a6b6029..0b7234e 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -151,6 +151,7 @@ noinst_HEADERS = \ ${srcdir}/Makefile.inc __LIB__libodp_la_SOURCES = \ + odp_atomic.c \ odp_barrier.c \ odp_buffer.c \ odp_classification.c \ diff --git a/platform/linux-generic/odp_atomic.c b/platform/linux-generic/odp_atomic.c new file mode 100644 index 0000000..996d09a --- /dev/null +++ b/platform/linux-generic/odp_atomic.c @@ -0,0 +1,24 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp/atomic.h> + +int odp_atomic_lock_free_u64(odp_atomic_op_t *atomic_op) +{ +#if __GCC_ATOMIC_LLONG_LOCK_FREE < 2 + /* All operations have locks */ + if (atomic_op) + atomic_op->all_bits = 0; + + return 0; +#else + /* All operations are lock-free */ + if (atomic_op) + atomic_op->all_bits = ~((uint32_t)0); + + return 2; +#endif +} -- 2.6.2 _______________________________________________ lng-odp mailing list lng-odp@lists.linaro.org https://lists.linaro.org/mailman/listinfo/lng-odp