[v9,1/6] lib/eal: implement the family of common bit operation APIs
Checks
Commit Message
Bitwise operation APIs are defined and used in a lot of PMDs,
which caused a huge code duplication. To reduce duplication,
this patch consolidates them into a common API family.
Signed-off-by: Joyce Kong <joyce.kong@arm.com>
Reviewed-by: Gavin Hu <gavin.hu@arm.com>
Reviewed-by: Phil Yang <phil.yang@arm.com>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
---
MAINTAINERS | 4 +
doc/api/doxy-api-index.md | 7 +-
lib/librte_eal/include/meson.build | 1 +
lib/librte_eal/include/rte_bitops.h | 258 ++++++++++++++++++++++++++++
4 files changed, 267 insertions(+), 3 deletions(-)
create mode 100644 lib/librte_eal/include/rte_bitops.h
Comments
24/04/2020 05:21, Joyce Kong:
> --- a/doc/api/doxy-api-index.md
> +++ b/doc/api/doxy-api-index.md
> - **containers**:
> + [bitmap] (@ref rte_bitmap.h),
> [mbuf] (@ref rte_mbuf.h),
> [mbuf pool ops] (@ref rte_mbuf_pool_ops.h),
> [ring] (@ref rte_ring.h),
> [stack] (@ref rte_stack.h),
> - [tailq] (@ref rte_tailq.h),
> - [bitmap] (@ref rte_bitmap.h)
> + [tailq] (@ref rte_tailq.h)
Why do you move bitmap?
I like having mbuf as the one.
24/04/2020 05:21, Joyce Kong:
> Bitwise operation APIs are defined and used in a lot of PMDs,
> which caused a huge code duplication. To reduce duplication,
> this patch consolidates them into a common API family.
[...]
> +rte_get_bit32_relaxed(unsigned int nr, volatile uint32_t *addr)
> +rte_set_bit32_relaxed(unsigned int nr, volatile uint32_t *addr)
> +rte_clear_bit32_relaxed(unsigned int nr, volatile uint32_t *addr)
> +rte_test_and_set_bit32_relaxed(unsigned int nr, volatile uint32_t *addr)
> +rte_test_and_clear_bit32_relaxed(unsigned int nr, volatile uint32_t *addr)
> +rte_get_bit64_relaxed(unsigned int nr, volatile uint64_t *addr)
> +rte_set_bit64_relaxed(unsigned int nr, volatile uint64_t *addr)
> +rte_clear_bit64_relaxed(unsigned int nr, volatile uint64_t *addr)
> +rte_test_and_set_bit64_relaxed(unsigned int nr, volatile uint64_t *addr)
> +rte_test_and_clear_bit64_relaxed(unsigned int nr, volatile uint64_t *addr)
Sorry, I have one more naming concern with this series.
I prefer a common namespace for bit operations.
Would you be OK to prefix all function names with rte_bit_relaxed_?
> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Friday, April 24, 2020 4:09 PM
> To: Joyce Kong <Joyce.Kong@arm.com>
> Cc: stephen@networkplumber.org; david.marchand@redhat.com;
> mb@smartsharesystems.com; jerinj@marvell.com;
> bruce.richardson@intel.com; ravi1.kumar@amd.com; rmody@marvell.com;
> shshaikh@marvell.com; xuanziyang2@huawei.com;
> cloud.wangxiaoyun@huawei.com; zhouguoyang@huawei.com; Honnappa
> Nagarahalli <Honnappa.Nagarahalli@arm.com>; Gavin Hu
> <Gavin.Hu@arm.com>; Phil Yang <Phil.Yang@arm.com>; nd <nd@arm.com>;
> dev@dpdk.org
> Subject: Re: [PATCH v9 1/6] lib/eal: implement the family of common bit
> operation APIs
>
> 24/04/2020 05:21, Joyce Kong:
> > --- a/doc/api/doxy-api-index.md
> > +++ b/doc/api/doxy-api-index.md
> > - **containers**:
> > + [bitmap] (@ref rte_bitmap.h),
> > [mbuf] (@ref rte_mbuf.h),
> > [mbuf pool ops] (@ref rte_mbuf_pool_ops.h),
> > [ring] (@ref rte_ring.h),
> > [stack] (@ref rte_stack.h),
> > - [tailq] (@ref rte_tailq.h),
> > - [bitmap] (@ref rte_bitmap.h)
> > + [tailq] (@ref rte_tailq.h)
>
> Why do you move bitmap?
> I like having mbuf as the one.
>
Yeah, will move bitmap back in v10.
> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Sunday, April 26, 2020 3:59 AM
> To: Joyce Kong <Joyce.Kong@arm.com>
> Cc: stephen@networkplumber.org; david.marchand@redhat.com;
> mb@smartsharesystems.com; jerinj@marvell.com;
> bruce.richardson@intel.com; ravi1.kumar@amd.com; rmody@marvell.com;
> shshaikh@marvell.com; xuanziyang2@huawei.com;
> cloud.wangxiaoyun@huawei.com; zhouguoyang@huawei.com; Honnappa
> Nagarahalli <Honnappa.Nagarahalli@arm.com>; Gavin Hu
> <Gavin.Hu@arm.com>; Phil Yang <Phil.Yang@arm.com>; dev@dpdk.org; nd
> <nd@arm.com>
> Subject: Re: [dpdk-dev] [PATCH v9 1/6] lib/eal: implement the family of
> common bit operation APIs
>
> 24/04/2020 05:21, Joyce Kong:
> > Bitwise operation APIs are defined and used in a lot of PMDs, which
> > caused a huge code duplication. To reduce duplication, this patch
> > consolidates them into a common API family.
> [...]
> > +rte_get_bit32_relaxed(unsigned int nr, volatile uint32_t *addr)
> > +rte_set_bit32_relaxed(unsigned int nr, volatile uint32_t *addr)
> > +rte_clear_bit32_relaxed(unsigned int nr, volatile uint32_t *addr)
> > +rte_test_and_set_bit32_relaxed(unsigned int nr, volatile uint32_t
> > +*addr) rte_test_and_clear_bit32_relaxed(unsigned int nr, volatile
> > +uint32_t *addr) rte_get_bit64_relaxed(unsigned int nr, volatile
> > +uint64_t *addr) rte_set_bit64_relaxed(unsigned int nr, volatile
> > +uint64_t *addr) rte_clear_bit64_relaxed(unsigned int nr, volatile
> > +uint64_t *addr) rte_test_and_set_bit64_relaxed(unsigned int nr,
> > +volatile uint64_t *addr) rte_test_and_clear_bit64_relaxed(unsigned
> > +int nr, volatile uint64_t *addr)
>
> Sorry, I have one more naming concern with this series.
> I prefer a common namespace for bit operations.
> Would you be OK to prefix all function names with rte_bit_relaxed_?
>
Hi Thomas,
Do you mean to rename the functions as 'rte_bit_relaxed_get_bit32'?
If the example is ok, I will modify as this in v10.
Thanks, Joyce
26/04/2020 09:18, Joyce Kong:
> From: Thomas Monjalon <thomas@monjalon.net>
> > 24/04/2020 05:21, Joyce Kong:
> > > Bitwise operation APIs are defined and used in a lot of PMDs, which
> > > caused a huge code duplication. To reduce duplication, this patch
> > > consolidates them into a common API family.
> > [...]
> > > +rte_get_bit32_relaxed(unsigned int nr, volatile uint32_t *addr)
> > > +rte_set_bit32_relaxed(unsigned int nr, volatile uint32_t *addr)
> > > +rte_clear_bit32_relaxed(unsigned int nr, volatile uint32_t *addr)
> > > +rte_test_and_set_bit32_relaxed(unsigned int nr, volatile uint32_t
> > > +*addr) rte_test_and_clear_bit32_relaxed(unsigned int nr, volatile
> > > +uint32_t *addr) rte_get_bit64_relaxed(unsigned int nr, volatile
> > > +uint64_t *addr) rte_set_bit64_relaxed(unsigned int nr, volatile
> > > +uint64_t *addr) rte_clear_bit64_relaxed(unsigned int nr, volatile
> > > +uint64_t *addr) rte_test_and_set_bit64_relaxed(unsigned int nr,
> > > +volatile uint64_t *addr) rte_test_and_clear_bit64_relaxed(unsigned
> > > +int nr, volatile uint64_t *addr)
> >
> > Sorry, I have one more naming concern with this series.
> > I prefer a common namespace for bit operations.
> > Would you be OK to prefix all function names with rte_bit_relaxed_?
> >
> Hi Thomas,
> Do you mean to rename the functions as 'rte_bit_relaxed_get_bit32'?
> If the example is ok, I will modify as this in v10.
Yes, thank you.
@@ -241,6 +241,10 @@ M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
F: lib/librte_eal/include/rte_bitmap.h
F: app/test/test_bitmap.c
+Bitops
+M: Joyce Kong <joyce.kong@arm.com>
+F: lib/librte_eal/include/rte_bitops.h
+
MCSlock - EXPERIMENTAL
M: Phil Yang <phil.yang@arm.com>
F: lib/librte_eal/include/generic/rte_mcslock.h
@@ -133,12 +133,12 @@ The public API headers are grouped by topics:
[BPF] (@ref rte_bpf.h)
- **containers**:
+ [bitmap] (@ref rte_bitmap.h),
[mbuf] (@ref rte_mbuf.h),
[mbuf pool ops] (@ref rte_mbuf_pool_ops.h),
[ring] (@ref rte_ring.h),
[stack] (@ref rte_stack.h),
- [tailq] (@ref rte_tailq.h),
- [bitmap] (@ref rte_bitmap.h)
+ [tailq] (@ref rte_tailq.h)
- **packet framework**:
* [port] (@ref rte_port.h):
@@ -165,7 +165,8 @@ The public API headers are grouped by topics:
[random] (@ref rte_random.h),
[config file] (@ref rte_cfgfile.h),
[key/value args] (@ref rte_kvargs.h),
- [string] (@ref rte_string_fns.h)
+ [string] (@ref rte_string_fns.h),
+ [bitops] (@ref rte_bitops.h)
- **debug**:
[jobstats] (@ref rte_jobstats.h),
@@ -6,6 +6,7 @@ includes += include_directories('.')
headers += files(
'rte_alarm.h',
'rte_bitmap.h',
+ 'rte_bitops.h',
'rte_branch_prediction.h',
'rte_bus.h',
'rte_class.h',
new file mode 100644
@@ -0,0 +1,258 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Arm Limited
+ */
+
+#ifndef _RTE_BITOPS_H_
+#define _RTE_BITOPS_H_
+
+/**
+ * @file
+ * Bit Operations
+ *
+ * This file defines a family of APIs for bit operations
+ * without enforcing memory ordering.
+ */
+
+#include <stdint.h>
+#include <rte_debug.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, volatile uint32_t *addr)
+{
+ RTE_ASSERT(nr < 32);
+
+ uint32_t mask = UINT32_C(1) << nr;
+ return (*addr) & 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, volatile uint32_t *addr)
+{
+ RTE_ASSERT(nr < 32);
+
+ uint32_t mask = UINT32_C(1) << nr;
+ *addr = (*addr) | mask;
+}
+
+/**
+ * @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, volatile uint32_t *addr)
+{
+ RTE_ASSERT(nr < 32);
+
+ uint32_t mask = UINT32_C(1) << nr;
+ *addr = (*addr) & (~mask);
+}
+
+/**
+ * @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, volatile uint32_t *addr)
+{
+ RTE_ASSERT(nr < 32);
+
+ uint32_t mask = UINT32_C(1) << nr;
+ uint32_t val = *addr;
+ *addr = val | mask;
+ return val & 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, volatile uint32_t *addr)
+{
+ RTE_ASSERT(nr < 32);
+
+ uint32_t mask = UINT32_C(1) << nr;
+ uint32_t val = *addr;
+ *addr = val & (~mask);
+ return val & 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, volatile uint64_t *addr)
+{
+ RTE_ASSERT(nr < 64);
+
+ uint64_t mask = UINT64_C(1) << nr;
+ return (*addr) & 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, volatile uint64_t *addr)
+{
+ RTE_ASSERT(nr < 64);
+
+ uint64_t mask = UINT64_C(1) << nr;
+ (*addr) = (*addr) | mask;
+}
+
+/**
+ * @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, volatile uint64_t *addr)
+{
+ RTE_ASSERT(nr < 64);
+
+ uint64_t mask = UINT64_C(1) << nr;
+ *addr = (*addr) & (~mask);
+}
+
+/**
+ * @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, volatile uint64_t *addr)
+{
+ RTE_ASSERT(nr < 64);
+
+ uint64_t mask = UINT64_C(1) << nr;
+ uint64_t val = *addr;
+ *addr = val | mask;
+ return val;
+}
+
+/**
+ * @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, volatile uint64_t *addr)
+{
+ RTE_ASSERT(nr < 64);
+
+ uint64_t mask = UINT64_C(1) << nr;
+ uint64_t val = *addr;
+ *addr = val & (~mask);
+ return val & mask;
+}
+
+#endif /* _RTE_BITOPS_H_ */