Signed-off-by: Ola Liljedahl <ola.liljed...@arm.com>
Reviewed-by: Brian Brooks <brian.bro...@arm.com>
Reviewed-by: Honnappa Nagarahalli <honnappa.nagaraha...@arm.com>
---
 platform/linux-generic/include/odp_bitset.h | 210 ++++++++++++++++++++++++++++
 1 file changed, 210 insertions(+)
 create mode 100644 platform/linux-generic/include/odp_bitset.h

diff --git a/platform/linux-generic/include/odp_bitset.h 
b/platform/linux-generic/include/odp_bitset.h
new file mode 100644
index 00000000..69b1a8dc
--- /dev/null
+++ b/platform/linux-generic/include/odp_bitset.h
@@ -0,0 +1,210 @@
+/* Copyright (c) 2017, ARM Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef _ODP_BITSET_H_
+#define _ODP_BITSET_H_
+
+#include <odp_cpu.h>
+
+#include <limits.h>
+
+/******************************************************************************
+ * bitset abstract data type
+ *****************************************************************************/
+/* This could be a struct of scalars to support larger bit sets */
+
+/*
+ * Size of atomic bit set. This limits the max number of threads,
+ * scheduler groups and reorder windows. On ARMv8/64-bit and x86-64, the
+ * (lock-free) max is 128
+ */
+
+/* Find a suitable data type that supports lock-free atomic operations */
+#if defined(__ARM_ARCH) &&  __ARM_ARCH == 8 &&  __ARM_64BIT_STATE == 1 && \
+       defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16
+#define LOCKFREE16
+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;
+}
+
+/* Return first-bit-set with StdC ffs() semantics */
+static inline uint32_t bitset_ffs(bitset_t b)
+{
+       return __builtin_ffsl(b);
+}
+
+/* Load-exclusive with memory ordering */
+static inline bitset_t bitset_monitor(bitset_t *bs, int mo)
+{
+       return monitor32(bs, mo);
+}
+
+#elif ATOM_BITSET_SIZE <= 64
+
+static inline bitset_t bitset_mask(uint32_t bit)
+{
+       return 1ULL << bit;
+}
+
+/* Return first-bit-set with StdC ffs() semantics */
+static inline uint32_t bitset_ffs(bitset_t b)
+{
+       return __builtin_ffsll(b);
+}
+
+/* Load-exclusive with memory ordering */
+static inline bitset_t bitset_monitor(bitset_t *bs, int mo)
+{
+       return monitor64(bs, mo);
+}
+
+#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;
+}
+
+/* Return first-bit-set with StdC ffs() semantics */
+static inline uint32_t bitset_ffs(bitset_t b)
+{
+       if ((uint64_t)b != 0)
+               return __builtin_ffsll((uint64_t)b);
+       else if ((b >> 64) != 0)
+               return __builtin_ffsll((uint64_t)(b >> 64)) + 64;
+       else
+               return 0;
+}
+
+/* Load-exclusive with memory ordering */
+static inline bitset_t bitset_monitor(bitset_t *bs, int mo)
+{
+       return monitor128(bs, mo);
+}
+
+#else
+#error Unsupported size of bit sets (ATOM_BITSET_SIZE)
+#endif
+
+/* Atomic load with memory ordering */
+static inline bitset_t atom_bitset_load(bitset_t *bs, int mo)
+{
+#ifdef LOCKFREE16
+       return __lockfree_load_16(bs, mo);
+#else
+       return __atomic_load_n(bs, mo);
+#endif
+}
+
+/* Atomic bit set with memory ordering */
+static inline void atom_bitset_set(bitset_t *bs, uint32_t bit, int mo)
+{
+#ifdef LOCKFREE16
+       (void)__lockfree_fetch_or_16(bs, bitset_mask(bit), mo);
+#else
+       (void)__atomic_fetch_or(bs, bitset_mask(bit), mo);
+#endif
+}
+
+/* Atomic bit clear with memory ordering */
+static inline void atom_bitset_clr(bitset_t *bs, uint32_t bit, int mo)
+{
+#ifdef LOCKFREE16
+       (void)__lockfree_fetch_and_16(bs, ~bitset_mask(bit), mo);
+#else
+       (void)__atomic_fetch_and(bs, ~bitset_mask(bit), mo);
+#endif
+}
+
+/* Atomic exchange with memory ordering */
+static inline bitset_t atom_bitset_xchg(bitset_t *bs, bitset_t neu, int mo)
+{
+#ifdef LOCKFREE16
+       return __lockfree_exchange_16(bs, neu, mo);
+#else
+       return __atomic_exchange_n(bs, neu, mo);
+#endif
+}
+
+/* Atomic compare&exchange with memory ordering */
+static inline bitset_t atom_bitset_cmpxchg(bitset_t *bs, bitset_t *old,
+                                          bitset_t neu, bool weak,
+                                          int mo_success, int mo_failure)
+{
+#ifdef LOCKFREE16
+       return __lockfree_compare_exchange_16(
+               bs, old, neu, weak, mo_success, mo_failure);
+#else
+       return __atomic_compare_exchange_n(
+               bs, old, neu, weak, mo_success, mo_failure);
+#endif
+}
+
+/* Return a & ~b */
+static inline bitset_t bitset_andn(bitset_t a, bitset_t b)
+{
+       return a & ~b;
+}
+
+static inline bool bitset_is_eql(bitset_t a, bitset_t b)
+{
+       return a == b;
+}
+
+static inline bitset_t bitset_clr(bitset_t bs, uint32_t bit)
+{
+       return bs & ~bitset_mask(bit);
+}
+
+static inline bitset_t bitset_set(bitset_t bs, uint32_t bit)
+{
+       return bs | bitset_mask(bit);
+}
+
+static inline bitset_t bitset_null(void)
+{
+       return 0U;
+}
+
+static inline bool bitset_is_null(bitset_t a)
+{
+       return a == 0U;
+}
+
+static inline bool bitset_is_set(bitset_t a, uint32_t bit)
+{
+       return (a & bitset_mask(bit)) != 0;
+}
+
+#endif
-- 
2.13.1

Reply via email to