[v9,1/6] lib/eal: implement the family of common bit operation APIs

Message ID 20200424032159.992-2-joyce.kong@arm.com (mailing list archive)
State Superseded, archived
Delegated to: David Marchand
Headers
Series implement common bit operation APIs |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-nxp-Performance success Performance Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-testing fail Testing issues

Commit Message

Joyce Kong April 24, 2020, 3:21 a.m. UTC
  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

Thomas Monjalon April 24, 2020, 8:08 a.m. UTC | #1
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.
  
Thomas Monjalon April 25, 2020, 7:59 p.m. UTC | #2
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_?
  
Joyce Kong April 26, 2020, 2:07 a.m. UTC | #3
> -----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.
  
Joyce Kong April 26, 2020, 7:18 a.m. UTC | #4
> -----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
  
Thomas Monjalon April 26, 2020, 9:23 a.m. UTC | #5
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.
  

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 1bf00d7e5..c5c255994 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -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
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index dff496be0..52e2be31d 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -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),
diff --git a/lib/librte_eal/include/meson.build b/lib/librte_eal/include/meson.build
index 6fd427494..3afb50a5b 100644
--- a/lib/librte_eal/include/meson.build
+++ b/lib/librte_eal/include/meson.build
@@ -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',
diff --git a/lib/librte_eal/include/rte_bitops.h b/lib/librte_eal/include/rte_bitops.h
new file mode 100644
index 000000000..4374f28e7
--- /dev/null
+++ b/lib/librte_eal/include/rte_bitops.h
@@ -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_ */