Hi Morten,
> -----Original Message-----
> From: Morten Brørup <mb@smartsharesystems.com>
> Sent: Monday, November 18, 2019 6:52 PM
> To: Joyce Kong (Arm Technology China) <Joyce.Kong@arm.com>;
> dev@dpdk.org
> Cc: nd <nd@arm.com>; thomas@monjalon.net; jerinj@marvell.com;
> stephen@networkplumber.org; david.marchand@redhat.com; Honnappa
> Nagarahalli <Honnappa.Nagarahalli@arm.com>; Gavin Hu (Arm Technology
> China) <Gavin.Hu@arm.com>; ravi1.kumar@amd.com; rmody@marvell.com;
> shshaikh@marvell.com; xuanziyang2@huawei.com;
> cloud.wangxiaoyun@huawei.com; zhouguoyang@huawei.com
> Subject: RE: [dpdk-dev] [PATCH v3 1/6] lib/eal: implement the family of rte
> bitoperation APIs
>
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Joyce Kong
> > Sent: Monday, November 18, 2019 11:07 AM
> >
>
> [snip]
>
> > +++ b/lib/librte_eal/common/include/rte_bitops.h
> > @@ -0,0 +1,474 @@
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + * Copyright(c) 2019 Arm Limited
> > + */
> > +
> > +#ifndef _RTE_BITOPS_H_
> > +#define _RTE_BITOPS_H_
> > +
> > +/**
> > + * @file
> > + * Bit Operations
> > + *
> > + * This file defines a API for bit operations without/with memory
> > ordering.
> > + */
> > +
> > +#include <stdint.h>
> > +#include <assert.h>
> > +#include <rte_compat.h>
> > +
> > +/*---------------------------- 32 bit operations
> > +---------------------
> > -------*/
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > notice
> > + *
> > + * Get the target bit from a 32-bit value without memory ordering.
> > + *
> > + * @param nr
> > + * The target bit to get.
> > + * @param addr
> > + * The address holding the bit.
> > + * @return
> > + * The target bit.
> > + */
> > +__rte_experimental
> > +static inline uint32_t
> > +rte_get_bit32_relaxed(unsigned int nr, unsigned long *addr) {
> > + assert(nr < 32);
> > +
> > + uint32_t mask = 1UL << nr;
> > + return __atomic_load_n(addr, __ATOMIC_RELAXED) & mask; }
>
> Address pointer should be: uint32_t *addr.
> Likewise in the other 32 bit functions.
>
> Use RTE_ASSERT() instead of assert().
> Likewise in all other functions.
>
> When setting the mask, consider using UINT32_C(1) from <stdint.h> instead
> of 1UL.
>
> [snip]
>
> > +
> > +/*---------------------------- 64 bit operations
> > +---------------------
> > -------*/
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > notice
> > + *
> > + * Get the target bit from a 64-bit value without memory ordering.
> > + *
> > + * @param nr
> > + * The target bit to get.
> > + * @param addr
> > + * The address holding the bit.
> > + * @return
> > + * The target bit.
> > + */
> > +__rte_experimental
> > +static inline uint64_t
> > +rte_get_bit64_relaxed(unsigned int nr, unsigned long *addr) {
> > + assert(nr < 64);
> > +
> > + uint64_t mask = 1UL << nr;
> > + return __atomic_load_n(addr, __ATOMIC_RELAXED) & mask; }
>
> Address pointer should be: uint64_t *addr.
> Likewise in the other 64 bit functions.
>
> Mask should be 1ULL, not 1UL. Or use UINT64_C(1) from <stdint.h> instead.
> Likewise in the other 64 bit functions.
>
> [snip]
>
>
> Med venlig hilsen / kind regards
> - Morten Brørup
>
>
Thanks! I shall address above comments in Patch v4 for both 32-bit and 64-bit functions.
@@ -181,4 +181,5 @@ The public API headers are grouped by topics:
[common] (@ref rte_common.h),
[experimental APIs] (@ref rte_compat.h),
[ABI versioning] (@ref rte_function_versioning.h),
- [version] (@ref rte_version.h)
+ [version] (@ref rte_version.h),
+ [bitops] (@ref rte_bitops.h)
@@ -19,6 +19,7 @@ INC += rte_malloc.h rte_keepalive.h rte_time.h
INC += rte_service.h rte_service_component.h
INC += rte_bitmap.h rte_vfio.h rte_hypervisor.h rte_test.h
INC += rte_reciprocal.h rte_fbarray.h rte_uuid.h
+INC += rte_bitops.h
GENERIC_INC := rte_atomic.h rte_byteorder.h rte_cycles.h rte_prefetch.h
GENERIC_INC += rte_memcpy.h rte_cpuflags.h
new file mode 100644
@@ -0,0 +1,474 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Arm Limited
+ */
+
+#ifndef _RTE_BITOPS_H_
+#define _RTE_BITOPS_H_
+
+/**
+ * @file
+ * Bit Operations
+ *
+ * This file defines a API for bit operations without/with memory ordering.
+ */
+
+#include <stdint.h>
+#include <assert.h>
+#include <rte_compat.h>
+
+/*---------------------------- 32 bit operations ----------------------------*/
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the target bit from a 32-bit value without memory ordering.
+ *
+ * @param nr
+ * The target bit to get.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The target bit.
+ */
+__rte_experimental
+static inline uint32_t
+rte_get_bit32_relaxed(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 32);
+
+ uint32_t mask = 1UL << nr;
+ return __atomic_load_n(addr, __ATOMIC_RELAXED) & mask;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set the target bit in a 32-bit value to 1 without memory ordering.
+ *
+ * @param nr
+ * The target bit to set.
+ * @param addr
+ * The address holding the bit.
+ */
+__rte_experimental
+static inline void
+rte_set_bit32_relaxed(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 32);
+
+ uint32_t mask = 1UL << nr;
+ __atomic_fetch_or(addr, mask, __ATOMIC_RELAXED);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Clear the target bit in a 32-bit value to 0 without memory ordering.
+ *
+ * @param nr
+ * The target bit to clear.
+ * @param addr
+ * The address holding the bit.
+ */
+__rte_experimental
+static inline void
+rte_clear_bit32_relaxed(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 32);
+
+ uint32_t mask = 1UL << nr;
+ __atomic_fetch_and(addr, ~mask, __ATOMIC_RELAXED);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Return the original bit from a 32-bit value, then set it to 1 without
+ * memory ordering.
+ *
+ * @param nr
+ * The target bit to get and set.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The original bit.
+ */
+__rte_experimental
+static inline uint32_t
+rte_test_and_set_bit32_relaxed(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 32);
+
+ uint32_t mask = 1UL << nr;
+ return __atomic_fetch_or(addr, mask, __ATOMIC_RELAXED) & mask;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Return the original bit from a 32-bit value, then clear it to 0 without
+ * memory ordering.
+ *
+ * @param nr
+ * The target bit to get and clear.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The original bit.
+ */
+__rte_experimental
+static inline uint32_t
+rte_test_and_clear_bit32_relaxed(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 32);
+
+ uint32_t mask = 1UL << nr;
+ return __atomic_fetch_and(addr, ~mask, __ATOMIC_RELAXED) & mask;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the target bit from a 32-bit value with memory ordering.
+ *
+ * @param nr
+ * The target bit to get.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The target bit.
+ */
+__rte_experimental
+static inline uint32_t
+rte_get_bit32(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 32);
+
+ uint32_t mask = 1UL << nr;
+ return __atomic_load_n(addr, __ATOMIC_ACQUIRE) & mask;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set the target bit in a 32-bit value to 1 with memory ordering.
+ *
+ * @param nr
+ * The target bit to set.
+ * @param addr
+ * The address holding the bit.
+ */
+__rte_experimental
+static inline void
+rte_set_bit32(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 32);
+
+ uint32_t mask = 1UL << nr;
+ __atomic_fetch_or(addr, mask, __ATOMIC_ACQ_REL);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Clear the target bit in a 32-bit value to 0 with memory ordering.
+ *
+ * @param nr
+ * The target bit to clear.
+ * @param addr
+ * The address holding the bit.
+ */
+__rte_experimental
+static inline void
+rte_clear_bit32(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 32);
+
+ uint32_t mask = 1UL << nr;
+ __atomic_fetch_and(addr, ~mask, __ATOMIC_ACQ_REL);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Return the original bit from a 32-bit value, then set it to 1 with
+ * memory ordering.
+ *
+ * @param nr
+ * The target bit to get and set.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The original bit.
+ */
+__rte_experimental
+static inline uint32_t
+rte_test_and_set_bit32(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 32);
+
+ uint32_t mask = 1UL << nr;
+ return __atomic_fetch_or(addr, mask, __ATOMIC_ACQ_REL) & mask;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Return the original bit from a 32-bit value, then clear it to 0 with
+ * memory ordering.
+ *
+ * @param nr
+ * The target bit to get and clear.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The original bit.
+ */
+__rte_experimental
+static inline uint32_t
+rte_test_and_clear_bit32(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 32);
+
+ uint32_t mask = 1UL << nr;
+ return __atomic_fetch_and(addr, ~mask, __ATOMIC_ACQ_REL) & mask;
+}
+
+/*---------------------------- 64 bit operations ----------------------------*/
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the target bit from a 64-bit value without memory ordering.
+ *
+ * @param nr
+ * The target bit to get.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The target bit.
+ */
+__rte_experimental
+static inline uint64_t
+rte_get_bit64_relaxed(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 64);
+
+ uint64_t mask = 1UL << nr;
+ return __atomic_load_n(addr, __ATOMIC_RELAXED) & mask;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set the target bit in a 64-bit value to 1 without memory ordering.
+ *
+ * @param nr
+ * The target bit to set.
+ * @param addr
+ * The address holding the bit.
+ */
+__rte_experimental
+static inline void
+rte_set_bit64_relaxed(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 64);
+
+ uint64_t mask = 1UL << nr;
+ __atomic_fetch_or(addr, mask, __ATOMIC_RELAXED);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Clear the target bit in a 64-bit value to 0 without memory ordering.
+ *
+ * @param nr
+ * The target bit to clear.
+ * @param addr
+ * The address holding the bit.
+ */
+__rte_experimental
+static inline void
+rte_clear_bit64_relaxed(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 64);
+
+ uint64_t mask = 1UL << nr;
+ __atomic_fetch_and(addr, ~mask, __ATOMIC_RELAXED);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Return the original bit from a 64-bit value, then set it to 1 without
+ * memory ordering.
+ *
+ * @param nr
+ * The target bit to get and set.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The original bit.
+ */
+__rte_experimental
+static inline uint64_t
+rte_test_and_set_bit64_relaxed(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 64);
+
+ uint64_t mask = 1UL << nr;
+ return __atomic_fetch_or(addr, mask, __ATOMIC_RELAXED) & mask;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Return the original bit from a 64-bit value, then clear it to 0 without
+ * memory ordering.
+ *
+ * @param nr
+ * The target bit to get and clear.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The original bit.
+ */
+__rte_experimental
+static inline uint64_t
+rte_test_and_clear_bit64_relaxed(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 64);
+
+ uint64_t mask = 1UL << nr;
+ return __atomic_fetch_and(addr, ~mask, __ATOMIC_RELAXED) & mask;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the target bit from a 64-bit value with memory ordering.
+ *
+ * @param nr
+ * The target bit to get.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The target bit.
+ */
+__rte_experimental
+static inline uint64_t
+rte_get_bit64(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 64);
+
+ uint64_t mask = 1UL << nr;
+ return __atomic_load_n(addr, __ATOMIC_ACQUIRE) & mask;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set the target bit in a 64-bit value to 1 with memory ordering.
+ *
+ * @param nr
+ * The target bit to set.
+ * @param addr
+ * The address holding the bit.
+ */
+__rte_experimental
+static inline void
+rte_set_bit64(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 64);
+
+ uint64_t mask = 1UL << nr;
+ __atomic_fetch_or(addr, mask, __ATOMIC_ACQ_REL);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Clear the target bit in a 64-bit value to 0 with memory ordering.
+ *
+ * @param nr
+ * The target bit to clear.
+ * @param addr
+ * The address holding the bit.
+ */
+__rte_experimental
+static inline void
+rte_clear_bit64(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 64);
+
+ uint64_t mask = 1UL << nr;
+ __atomic_fetch_and(addr, ~mask, __ATOMIC_ACQ_REL);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Return the original bit from a 64-bit value, then set it to 1 with
+ * memory ordering.
+ *
+ * @param nr
+ * The target bit to get and set.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The original bit.
+ */
+__rte_experimental
+static inline uint64_t
+rte_test_and_set_bit64(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 64);
+
+ uint64_t mask = 1UL << nr;
+ return __atomic_fetch_or(addr, mask, __ATOMIC_ACQ_REL) & mask;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Return the original bit from a 64-bit value, then clear it to 0 with
+ * memory ordering.
+ *
+ * @param nr
+ * The target bit to get and clear.
+ * @param addr
+ * The address holding the bit.
+ * @return
+ * The original bit.
+ */
+__rte_experimental
+static inline uint64_t
+rte_test_and_clear_bit64(unsigned int nr, unsigned long *addr)
+{
+ assert(nr < 64);
+
+ uint64_t mask = 1UL << nr;
+ return __atomic_fetch_and(addr, ~mask, __ATOMIC_ACQ_REL) & mask;
+}
+#endif /* _RTE_BITOPS_H_ */
@@ -52,6 +52,7 @@ common_headers = files(
'include/rte_alarm.h',
'include/rte_branch_prediction.h',
'include/rte_bus.h',
+ 'include/rte_bitops.h',
'include/rte_bitmap.h',
'include/rte_class.h',
'include/rte_common.h',