diff options
author | Malvika Gupta <Malvika.Gupta@arm.com> | 2021-02-23 12:00:41 -0600 |
---|---|---|
committer | Matias Elo <matias.elo@nokia.com> | 2021-03-29 11:30:41 +0300 |
commit | ad9c14ffa4363598995bf11b65e07cb4192670a7 (patch) | |
tree | e940bc9d10d87b2b742af57ea086c4dd798487db /platform/linux-generic/arch/aarch64 | |
parent | 30c6605eff3ae63111929bafc3056859da276607 (diff) |
linux-gen: bitset: move aarch64 specific code to arch files
On arm64 systems, the build fails with the --disable-host-optimization
compiler flag as it is unable to locate definitions of lockless APIs
used in atomic bit operations since these declarations are present in
arch/aarch64/odp_atomic.h files Consequently, the aarch64 specific code
has been moved to the arch-specific file while the reminder code has been
moved under the default linux-generic implementation.
Signed-off-by: Malvika Gupta <Malvika.Gupta@arm.com>
Reviewed-by: Govindarajan Mohandoss <govindarajan.mohandoss@arm.com>
Reviewed-by: Matias Elo <matias.elo@nokia.com>
Diffstat (limited to 'platform/linux-generic/arch/aarch64')
-rw-r--r-- | platform/linux-generic/arch/aarch64/odp_atomic.h | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/platform/linux-generic/arch/aarch64/odp_atomic.h b/platform/linux-generic/arch/aarch64/odp_atomic.h index 6cf114f2e..c7a28fc2c 100644 --- a/platform/linux-generic/arch/aarch64/odp_atomic.h +++ b/platform/linux-generic/arch/aarch64/odp_atomic.h @@ -12,6 +12,8 @@ #error This file should not be included directly, please include odp_cpu.h #endif +#include <limits.h> + #ifdef CONFIG_DMBSTR #define atomic_store_release(loc, val, ro) \ @@ -241,4 +243,84 @@ static inline int lockfree_check_u128(void) return 1; } +/** Atomic bit set operations with memory ordering */ +#if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 +typedef __int128 bitset_t; +#define ATOM_BITSET_SIZE (CHAR_BIT * __SIZEOF_INT128__) + +#elif __GCC_ATOMIC_LLONG_LOCK_FREE == 2 && \ + __SIZEOF_LONG_LONG__ != __SIZEOF_LONG__ +typedef unsigned long long bitset_t; +#define ATOM_BITSET_SIZE (CHAR_BIT * __SIZEOF_LONG_LONG__) + +#elif __GCC_ATOMIC_LONG_LOCK_FREE == 2 && __SIZEOF_LONG__ != __SIZEOF_INT__ +typedef unsigned long bitset_t; +#define ATOM_BITSET_SIZE (CHAR_BIT * __SIZEOF_LONG__) + +#elif __GCC_ATOMIC_INT_LOCK_FREE == 2 +typedef unsigned int bitset_t; +#define ATOM_BITSET_SIZE (CHAR_BIT * __SIZEOF_INT__) + +#else +/* Target does not support lock-free atomic operations */ +typedef unsigned int bitset_t; +#define ATOM_BITSET_SIZE (CHAR_BIT * __SIZEOF_INT__) +#endif + +#if ATOM_BITSET_SIZE <= 32 + +static inline bitset_t bitset_mask(uint32_t bit) +{ + return 1UL << bit; +} + +#elif ATOM_BITSET_SIZE <= 64 + +static inline bitset_t bitset_mask(uint32_t bit) +{ + return 1ULL << bit; +} + +#elif ATOM_BITSET_SIZE <= 128 + +static inline bitset_t bitset_mask(uint32_t bit) +{ + if (bit < 64) + return 1ULL << bit; + else + return (unsigned __int128)(1ULL << (bit - 64)) << 64; +} + +#else +#error Unsupported size of bit sets (ATOM_BITSET_SIZE) +#endif + +static inline bitset_t atom_bitset_load(bitset_t *bs, int mo) +{ + return __lockfree_load_16(bs, mo); +} + +static inline void atom_bitset_set(bitset_t *bs, uint32_t bit, int mo) +{ + (void)__lockfree_fetch_or_16(bs, bitset_mask(bit), mo); +} + +static inline void atom_bitset_clr(bitset_t *bs, uint32_t bit, int mo) +{ + (void)__lockfree_fetch_and_16(bs, ~bitset_mask(bit), mo); +} + +static inline bitset_t atom_bitset_xchg(bitset_t *bs, bitset_t neu, int mo) +{ + return __lockfree_exchange_16(bs, neu, mo); +} + +static inline bitset_t atom_bitset_cmpxchg(bitset_t *bs, bitset_t *old, + bitset_t neu, bool weak, + int mo_success, int mo_failure) +{ + return __lockfree_compare_exchange_16(bs, old, neu, weak, mo_success, + mo_failure); +} + #endif /* PLATFORM_LINUXGENERIC_ARCH_ARM_ODP_ATOMIC_H */ |