[v8,1/9] memarea: introduce memarea library

Message ID 20221011121720.2657-2-fengchengwen@huawei.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series introduce memarea library |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

fengchengwen Oct. 11, 2022, 12:17 p.m. UTC
  The memarea library is an allocator of variable-size object which based
on a memory region.

This patch provides create/destroy API.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
---
 MAINTAINERS                            |   5 +
 doc/api/doxy-api-index.md              |   3 +-
 doc/api/doxy-api.conf.in               |   1 +
 doc/guides/prog_guide/index.rst        |   1 +
 doc/guides/prog_guide/memarea_lib.rst  |  39 ++++++
 doc/guides/rel_notes/release_22_11.rst |   6 +
 lib/eal/common/eal_common_log.c        |   1 +
 lib/eal/include/rte_log.h              |   1 +
 lib/memarea/memarea_private.h          |  33 ++++++
 lib/memarea/meson.build                |  16 +++
 lib/memarea/rte_memarea.c              | 158 +++++++++++++++++++++++++
 lib/memarea/rte_memarea.h              | 136 +++++++++++++++++++++
 lib/memarea/version.map                |  12 ++
 lib/meson.build                        |   1 +
 14 files changed, 412 insertions(+), 1 deletion(-)
 create mode 100644 doc/guides/prog_guide/memarea_lib.rst
 create mode 100644 lib/memarea/memarea_private.h
 create mode 100644 lib/memarea/meson.build
 create mode 100644 lib/memarea/rte_memarea.c
 create mode 100644 lib/memarea/rte_memarea.h
 create mode 100644 lib/memarea/version.map
  

Comments

Dmitry Kozlyuk Oct. 11, 2022, 3:58 p.m. UTC | #1
2022-10-11 12:17 (UTC+0000), Chengwen Feng:
[...]
> diff --git a/doc/guides/prog_guide/memarea_lib.rst b/doc/guides/prog_guide/memarea_lib.rst
> new file mode 100644
> index 0000000000..85ad57145f
> --- /dev/null
> +++ b/doc/guides/prog_guide/memarea_lib.rst
> @@ -0,0 +1,39 @@
> +..  SPDX-License-Identifier: BSD-3-Clause
> +    Copyright(c) 2022 HiSilicon Limited
> +
> +Memarea Library
> +===============
> +
> +Introduction
> +------------
> +
> +The memarea library provides an allocator of variable-size objects, it is
> +oriented towards the application layer, which could provides 'region-based
> +memory management' function [1].
> +
> +The main features are as follows:
> +
> +* The allocated object aligned at ``RTE_CACHE_LINE_SIZE`` default.

Isn't this an implementation detail?
Stating it in the API description limits optimization opportunities.
Cache line alignment is good in many cases,
but it can also be a waste of space,
e.g. for a thread-unsafe region for small objects.
Can this limitation only (temporarily?) apply to user memory?
Or can the minimal alignment be a property of memarea?

> +
> +* The memory region can be initialized from the following memory sources:
> +  a) HEAP: e.g. invoke ``rte_malloc_socket``. b) LIBC: e.g. invoke
> +  posix_memalign to obtain. c) User memory: it can be from e.g. rte_extmem_xxx
> +  as long as it is available. d) Another memarea: it can be allocated from
> +  another memarea.

I think mentioning rte_extmem_xxx() is bogus
because user memory does not need to be registered with DPDK
(I understand it's an example, but still an unrelated reference).
Please format as a list.

> +
> +* It provides refcnt feature which could be useful in multi-reader scenario.
> +
> +* It supports MT-safe as long as it's specified at creation time.
> +
> +Library API Overview
> +--------------------
> +
> +The ``rte_memarea_create()`` function is used to create a memarea, the function
> +returns the pointer to the created memarea or ``NULL`` if the creation failed.
> +
> +The ``rte_memarea_destroy()`` function is used to destroy a memarea.
> +
> +Reference
> +---------
> +
> +[1] https://en.wikipedia.org/wiki/Region-based_memory_management
> diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
> index 2da8bc9661..f5a67cec7b 100644
> --- a/doc/guides/rel_notes/release_22_11.rst
> +++ b/doc/guides/rel_notes/release_22_11.rst
> @@ -63,6 +63,12 @@ New Features
>    In theory this implementation should work with any target based on
>    ``LoongArch`` ISA.
>  
> +* **Added memarea library.**
> +
> +  The memarea library is an allocator of variable-size objects, it is oriented
> +  towards the application layer, which could provides 'region-based memory
> +  management' function.

"which could provides" -> "providing"

> +
>  * **Added support for multiple mbuf pools per ethdev Rx queue.**
>  
>    The capability allows application to provide many mempools
[...]
  
fengchengwen Oct. 12, 2022, 4:06 a.m. UTC | #2
Hi Dmitry,

On 2022/10/11 23:58, Dmitry Kozlyuk wrote:
> 2022-10-11 12:17 (UTC+0000), Chengwen Feng:
> [...]
>> diff --git a/doc/guides/prog_guide/memarea_lib.rst b/doc/guides/prog_guide/memarea_lib.rst
>> new file mode 100644
>> index 0000000000..85ad57145f
>> --- /dev/null
>> +++ b/doc/guides/prog_guide/memarea_lib.rst
>> @@ -0,0 +1,39 @@
>> +..  SPDX-License-Identifier: BSD-3-Clause
>> +    Copyright(c) 2022 HiSilicon Limited
>> +
>> +Memarea Library
>> +===============
>> +
>> +Introduction
>> +------------
>> +
>> +The memarea library provides an allocator of variable-size objects, it is
>> +oriented towards the application layer, which could provides 'region-based
>> +memory management' function [1].
>> +
>> +The main features are as follows:
>> +
>> +* The allocated object aligned at ``RTE_CACHE_LINE_SIZE`` default.
> 
> Isn't this an implementation detail?
> Stating it in the API description limits optimization opportunities.
> Cache line alignment is good in many cases,
> but it can also be a waste of space,
> e.g. for a thread-unsafe region for small objects.
> Can this limitation only (temporarily?) apply to user memory?
> Or can the minimal alignment be a property of memarea?

You are right, to be more general, I'll add the align parameter to rte_memarea_alloc instead of stating it here.

> 
>> +
>> +* The memory region can be initialized from the following memory sources:
>> +  a) HEAP: e.g. invoke ``rte_malloc_socket``. b) LIBC: e.g. invoke
>> +  posix_memalign to obtain. c) User memory: it can be from e.g. rte_extmem_xxx
>> +  as long as it is available. d) Another memarea: it can be allocated from
>> +  another memarea.
> 
> I think mentioning rte_extmem_xxx() is bogus
> because user memory does not need to be registered with DPDK
> (I understand it's an example, but still an unrelated reference).
> Please format as a list.

okay

> 
>> +
>> +* It provides refcnt feature which could be useful in multi-reader scenario.
>> +
>> +* It supports MT-safe as long as it's specified at creation time.
>> +
>> +Library API Overview
>> +--------------------
>> +
>> +The ``rte_memarea_create()`` function is used to create a memarea, the function
>> +returns the pointer to the created memarea or ``NULL`` if the creation failed.
>> +
>> +The ``rte_memarea_destroy()`` function is used to destroy a memarea.
>> +
>> +Reference
>> +---------
>> +
>> +[1] https://en.wikipedia.org/wiki/Region-based_memory_management
>> diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
>> index 2da8bc9661..f5a67cec7b 100644
>> --- a/doc/guides/rel_notes/release_22_11.rst
>> +++ b/doc/guides/rel_notes/release_22_11.rst
>> @@ -63,6 +63,12 @@ New Features
>>    In theory this implementation should work with any target based on
>>    ``LoongArch`` ISA.
>>  
>> +* **Added memarea library.**
>> +
>> +  The memarea library is an allocator of variable-size objects, it is oriented
>> +  towards the application layer, which could provides 'region-based memory
>> +  management' function.
> 
> "which could provides" -> "providing"

okay

> 
>> +
>>  * **Added support for multiple mbuf pools per ethdev Rx queue.**
>>  
>>    The capability allows application to provide many mempools
> [...]
> .
>
  
fengchengwen Oct. 13, 2022, 10:45 a.m. UTC | #3
Sorry to self-reply.

On 2022/10/12 12:06, fengchengwen wrote:
> Hi Dmitry,
> 
> On 2022/10/11 23:58, Dmitry Kozlyuk wrote:
>> 2022-10-11 12:17 (UTC+0000), Chengwen Feng:
>> [...]
>>> diff --git a/doc/guides/prog_guide/memarea_lib.rst b/doc/guides/prog_guide/memarea_lib.rst
>>> new file mode 100644
>>> index 0000000000..85ad57145f
>>> --- /dev/null
>>> +++ b/doc/guides/prog_guide/memarea_lib.rst
>>> @@ -0,0 +1,39 @@
>>> +..  SPDX-License-Identifier: BSD-3-Clause
>>> +    Copyright(c) 2022 HiSilicon Limited
>>> +
>>> +Memarea Library
>>> +===============
>>> +
>>> +Introduction
>>> +------------
>>> +
>>> +The memarea library provides an allocator of variable-size objects, it is
>>> +oriented towards the application layer, which could provides 'region-based
>>> +memory management' function [1].
>>> +
>>> +The main features are as follows:
>>> +
>>> +* The allocated object aligned at ``RTE_CACHE_LINE_SIZE`` default.
>>
>> Isn't this an implementation detail?
>> Stating it in the API description limits optimization opportunities.
>> Cache line alignment is good in many cases,
>> but it can also be a waste of space,
>> e.g. for a thread-unsafe region for small objects.
>> Can this limitation only (temporarily?) apply to user memory?
>> Or can the minimal alignment be a property of memarea?
> 
> You are right, to be more general, I'll add the align parameter to rte_memarea_alloc instead of stating it here.

The memarea is targeted to not so general usage, so v9 doesn't add align parameter to rte_memarea_alloc, at least from the internal feedback.
We could add rte_memarea_align_alloc() if the align requirement does exist.

> 
>>
>>> +
>>> +* The memory region can be initialized from the following memory sources:
>>> +  a) HEAP: e.g. invoke ``rte_malloc_socket``. b) LIBC: e.g. invoke
>>> +  posix_memalign to obtain. c) User memory: it can be from e.g. rte_extmem_xxx
>>> +  as long as it is available. d) Another memarea: it can be allocated from
>>> +  another memarea.
>>
>> I think mentioning rte_extmem_xxx() is bogus
>> because user memory does not need to be registered with DPDK
>> (I understand it's an example, but still an unrelated reference).
>> Please format as a list.
> 
> okay
> 
>>
>>> +
>>> +* It provides refcnt feature which could be useful in multi-reader scenario.
>>> +
>>> +* It supports MT-safe as long as it's specified at creation time.
>>> +
>>> +Library API Overview
>>> +--------------------
>>> +
>>> +The ``rte_memarea_create()`` function is used to create a memarea, the function
>>> +returns the pointer to the created memarea or ``NULL`` if the creation failed.
>>> +
>>> +The ``rte_memarea_destroy()`` function is used to destroy a memarea.
>>> +
>>> +Reference
>>> +---------
>>> +
>>> +[1] https://en.wikipedia.org/wiki/Region-based_memory_management
>>> diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
>>> index 2da8bc9661..f5a67cec7b 100644
>>> --- a/doc/guides/rel_notes/release_22_11.rst
>>> +++ b/doc/guides/rel_notes/release_22_11.rst
>>> @@ -63,6 +63,12 @@ New Features
>>>    In theory this implementation should work with any target based on
>>>    ``LoongArch`` ISA.
>>>  
>>> +* **Added memarea library.**
>>> +
>>> +  The memarea library is an allocator of variable-size objects, it is oriented
>>> +  towards the application layer, which could provides 'region-based memory
>>> +  management' function.
>>
>> "which could provides" -> "providing"
> 
> okay
> 
>>
>>> +
>>>  * **Added support for multiple mbuf pools per ethdev Rx queue.**
>>>  
>>>    The capability allows application to provide many mempools
>> [...]
>> .
>>
> 
> .
>
  

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 2bd4a55f1b..3d8d4c2dbe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1551,6 +1551,11 @@  F: app/test/test_lpm*
 F: app/test/test_func_reentrancy.c
 F: app/test/test_xmmt_ops.h
 
+Memarea - EXPERIMENTAL
+M: Chengwen Feng <fengchengwen@huawei.com>
+F: lib/memarea
+F: doc/guides/prog_guide/memarea_lib.rst
+
 Membership - EXPERIMENTAL
 M: Yipeng Wang <yipeng1.wang@intel.com>
 M: Sameh Gobriel <sameh.gobriel@intel.com>
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index de488c7abf..24456604f8 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -62,7 +62,8 @@  The public API headers are grouped by topics:
   [memzone](@ref rte_memzone.h),
   [mempool](@ref rte_mempool.h),
   [malloc](@ref rte_malloc.h),
-  [memcpy](@ref rte_memcpy.h)
+  [memcpy](@ref rte_memcpy.h),
+  [memarea](@ref rte_memarea.h)
 
 - **timers**:
   [cycles](@ref rte_cycles.h),
diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in
index f0886c3bd1..8334ebcbd6 100644
--- a/doc/api/doxy-api.conf.in
+++ b/doc/api/doxy-api.conf.in
@@ -53,6 +53,7 @@  INPUT                   = @TOPDIR@/doc/api/doxy-api-index.md \
                           @TOPDIR@/lib/latencystats \
                           @TOPDIR@/lib/lpm \
                           @TOPDIR@/lib/mbuf \
+                          @TOPDIR@/lib/memarea \
                           @TOPDIR@/lib/member \
                           @TOPDIR@/lib/mempool \
                           @TOPDIR@/lib/meter \
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index 8564883018..e9015d65e3 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -37,6 +37,7 @@  Programmer's Guide
     hash_lib
     toeplitz_hash_lib
     efd_lib
+    memarea_lib
     member_lib
     lpm_lib
     lpm6_lib
diff --git a/doc/guides/prog_guide/memarea_lib.rst b/doc/guides/prog_guide/memarea_lib.rst
new file mode 100644
index 0000000000..85ad57145f
--- /dev/null
+++ b/doc/guides/prog_guide/memarea_lib.rst
@@ -0,0 +1,39 @@ 
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2022 HiSilicon Limited
+
+Memarea Library
+===============
+
+Introduction
+------------
+
+The memarea library provides an allocator of variable-size objects, it is
+oriented towards the application layer, which could provides 'region-based
+memory management' function [1].
+
+The main features are as follows:
+
+* The allocated object aligned at ``RTE_CACHE_LINE_SIZE`` default.
+
+* The memory region can be initialized from the following memory sources:
+  a) HEAP: e.g. invoke ``rte_malloc_socket``. b) LIBC: e.g. invoke
+  posix_memalign to obtain. c) User memory: it can be from e.g. rte_extmem_xxx
+  as long as it is available. d) Another memarea: it can be allocated from
+  another memarea.
+
+* It provides refcnt feature which could be useful in multi-reader scenario.
+
+* It supports MT-safe as long as it's specified at creation time.
+
+Library API Overview
+--------------------
+
+The ``rte_memarea_create()`` function is used to create a memarea, the function
+returns the pointer to the created memarea or ``NULL`` if the creation failed.
+
+The ``rte_memarea_destroy()`` function is used to destroy a memarea.
+
+Reference
+---------
+
+[1] https://en.wikipedia.org/wiki/Region-based_memory_management
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index 2da8bc9661..f5a67cec7b 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -63,6 +63,12 @@  New Features
   In theory this implementation should work with any target based on
   ``LoongArch`` ISA.
 
+* **Added memarea library.**
+
+  The memarea library is an allocator of variable-size objects, it is oriented
+  towards the application layer, which could provides 'region-based memory
+  management' function.
+
 * **Added support for multiple mbuf pools per ethdev Rx queue.**
 
   The capability allows application to provide many mempools
diff --git a/lib/eal/common/eal_common_log.c b/lib/eal/common/eal_common_log.c
index bd7b188ceb..3d62af59c6 100644
--- a/lib/eal/common/eal_common_log.c
+++ b/lib/eal/common/eal_common_log.c
@@ -369,6 +369,7 @@  static const struct logtype logtype_strings[] = {
 	{RTE_LOGTYPE_EFD,        "lib.efd"},
 	{RTE_LOGTYPE_EVENTDEV,   "lib.eventdev"},
 	{RTE_LOGTYPE_GSO,        "lib.gso"},
+	{RTE_LOGTYPE_MEMAREA,    "lib.memarea"},
 	{RTE_LOGTYPE_USER1,      "user1"},
 	{RTE_LOGTYPE_USER2,      "user2"},
 	{RTE_LOGTYPE_USER3,      "user3"},
diff --git a/lib/eal/include/rte_log.h b/lib/eal/include/rte_log.h
index 25ce42cdfc..708f3a39dd 100644
--- a/lib/eal/include/rte_log.h
+++ b/lib/eal/include/rte_log.h
@@ -48,6 +48,7 @@  extern "C" {
 #define RTE_LOGTYPE_EFD       18 /**< Log related to EFD. */
 #define RTE_LOGTYPE_EVENTDEV  19 /**< Log related to eventdev. */
 #define RTE_LOGTYPE_GSO       20 /**< Log related to GSO. */
+#define RTE_LOGTYPE_MEMAREA   21 /**< Log related to memarea. */
 
 /* these log types can be used in an application */
 #define RTE_LOGTYPE_USER1     24 /**< User-defined log type 1. */
diff --git a/lib/memarea/memarea_private.h b/lib/memarea/memarea_private.h
new file mode 100644
index 0000000000..59be9c1d00
--- /dev/null
+++ b/lib/memarea/memarea_private.h
@@ -0,0 +1,33 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 HiSilicon Limited
+ */
+
+#ifndef MEMAREA_PRIVATE_H
+#define MEMAREA_PRIVATE_H
+
+#include <rte_memarea.h>
+
+#define MEMAREA_AVAILABLE_ELEM_MAGIC	0xbeef1234
+#define MEMAREA_ALLOCATED_ELEM_MAGIC	0xbeef1230
+#define MEMAREA_AVAILABLE_ELEM_COOKIE	0xffffffff
+
+struct memarea_elem {
+	TAILQ_ENTRY(memarea_elem) elem_node;
+	TAILQ_ENTRY(memarea_elem) free_node;
+	size_t   size;
+	uint32_t magic;
+	uint32_t cookie;
+	int32_t  refcnt; /* Non-zero indicates that it has been allocated */
+} __rte_cache_aligned;
+
+TAILQ_HEAD(memarea_elem_list, memarea_elem);
+
+struct rte_memarea {
+	struct rte_memarea_param init;
+	rte_spinlock_t           lock;
+	void                    *area_addr;
+	struct memarea_elem_list elem_list;
+	struct memarea_elem_list free_list;
+} __rte_cache_aligned;
+
+#endif /* MEMAREA_PRIVATE_H */
diff --git a/lib/memarea/meson.build b/lib/memarea/meson.build
new file mode 100644
index 0000000000..0a74fb4cd1
--- /dev/null
+++ b/lib/memarea/meson.build
@@ -0,0 +1,16 @@ 
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2022 HiSilicon Limited
+
+if is_windows
+    build = false
+    reason = 'not supported on Windows'
+    subdir_done()
+endif
+
+sources = files(
+        'rte_memarea.c',
+)
+headers = files(
+        'rte_memarea.h',
+)
+deps += []
diff --git a/lib/memarea/rte_memarea.c b/lib/memarea/rte_memarea.c
new file mode 100644
index 0000000000..85975029e2
--- /dev/null
+++ b/lib/memarea/rte_memarea.c
@@ -0,0 +1,158 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 HiSilicon Limited
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_spinlock.h>
+
+#include "rte_memarea.h"
+#include "memarea_private.h"
+
+static int
+memarea_check_param(const struct rte_memarea_param *init)
+{
+	size_t len;
+
+	if (init == NULL) {
+		RTE_LOG(ERR, MEMAREA, "memarea init param is NULL!\n");
+		return -EINVAL;
+	}
+
+	len = strnlen(init->name, RTE_MEMAREA_NAMESIZE);
+	if (len == 0 || len >= RTE_MEMAREA_NAMESIZE) {
+		RTE_LOG(ERR, MEMAREA, "memarea name size %zu invalid!\n", len);
+		return -EINVAL;
+	}
+
+	if (init->source != RTE_MEMAREA_SOURCE_HEAP &&
+	    init->source != RTE_MEMAREA_SOURCE_LIBC &&
+	    init->source != RTE_MEMAREA_SOURCE_USER &&
+	    init->source != RTE_MEMAREA_SOURCE_MEMAREA) {
+		RTE_LOG(ERR, MEMAREA, "memarea: %s source: %d not supported!\n",
+			init->name, init->source);
+		return -EINVAL;
+	}
+
+	if (init->total_sz <= sizeof(struct memarea_elem)) {
+		RTE_LOG(ERR, MEMAREA, "memarea: %s total-size: %zu too small!\n",
+			init->name, init->total_sz);
+		return -EINVAL;
+	}
+
+	if (init->source == RTE_MEMAREA_SOURCE_USER && init->user_addr == NULL) {
+		RTE_LOG(ERR, MEMAREA, "memarea: %s user memory address is NULL!\n", init->name);
+		return -EINVAL;
+	}
+
+	if (init->source == RTE_MEMAREA_SOURCE_USER &&
+	    ((uintptr_t)init->user_addr & (RTE_CACHE_LINE_SIZE - 1))) {
+		RTE_LOG(ERR, MEMAREA, "memarea: %s user memory address should align: %d!\n",
+			init->name, RTE_CACHE_LINE_SIZE);
+		return -EINVAL;
+	}
+
+	if (init->source == RTE_MEMAREA_SOURCE_MEMAREA && init->src_memarea == NULL) {
+		RTE_LOG(ERR, MEMAREA, "memarea: %s source memarea is NULL!\n", init->name);
+		return -EINVAL;
+	}
+
+	if (init->alg != RTE_MEMAREA_ALG_NEXTFIT) {
+		RTE_LOG(ERR, MEMAREA, "memarea: %s alg: %d not supported!\n",
+			init->name, init->alg);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void *
+memarea_alloc_from_libc(size_t size)
+{
+	void *ptr = NULL;
+	int ret;
+
+	ret = posix_memalign(&ptr, RTE_CACHE_LINE_SIZE, size);
+	if (ret)
+		return NULL;
+	return ptr;
+}
+
+static void *
+memarea_alloc_area(const struct rte_memarea_param *init)
+{
+	void *ptr = NULL;
+
+	if (init->source == RTE_MEMAREA_SOURCE_HEAP)
+		ptr = rte_malloc_socket(NULL, init->total_sz, RTE_CACHE_LINE_SIZE,
+					init->numa_socket);
+	else if (init->source == RTE_MEMAREA_SOURCE_LIBC)
+		ptr = memarea_alloc_from_libc(init->total_sz);
+	else if (init->source == RTE_MEMAREA_SOURCE_USER)
+		ptr = init->user_addr;
+
+	if (ptr == NULL)
+		RTE_LOG(ERR, MEMAREA, "memarea: %s alloc memory area fail!\n", init->name);
+
+	return ptr;
+}
+
+struct rte_memarea *
+rte_memarea_create(const struct rte_memarea_param *init)
+{
+	struct memarea_elem *elem;
+	struct rte_memarea *ma;
+	void *addr;
+	int ret;
+
+	ret = memarea_check_param(init);
+	if (ret)
+		return NULL;
+
+	addr = memarea_alloc_area(init);
+	if (addr == NULL)
+		return NULL;
+
+	ma = rte_zmalloc(NULL, sizeof(struct rte_memarea), RTE_CACHE_LINE_SIZE);
+	if (ma == NULL) {
+		RTE_LOG(ERR, MEMAREA, "malloc memarea: %s management obj fail!\n", init->name);
+		return NULL;
+	}
+
+	ma->init = *init;
+	rte_spinlock_init(&ma->lock);
+	TAILQ_INIT(&ma->elem_list);
+	TAILQ_INIT(&ma->free_list);
+	ma->area_addr = addr;
+	elem = addr;
+	TAILQ_INSERT_TAIL(&ma->elem_list, elem, elem_node);
+	TAILQ_INSERT_TAIL(&ma->free_list, elem, free_node);
+	elem->size = init->total_sz - sizeof(struct memarea_elem);
+	elem->magic = MEMAREA_AVAILABLE_ELEM_MAGIC;
+	elem->cookie = MEMAREA_AVAILABLE_ELEM_COOKIE;
+	elem->refcnt = 0;
+
+	return ma;
+}
+
+static void
+memarea_free_area(struct rte_memarea *ma)
+{
+	if (ma->init.source == RTE_MEMAREA_SOURCE_HEAP)
+		rte_free(ma->area_addr);
+	else if (ma->init.source == RTE_MEMAREA_SOURCE_LIBC)
+		free(ma->area_addr);
+}
+
+void
+rte_memarea_destroy(struct rte_memarea *ma)
+{
+	if (ma == NULL)
+		return;
+	memarea_free_area(ma);
+	rte_free(ma);
+}
diff --git a/lib/memarea/rte_memarea.h b/lib/memarea/rte_memarea.h
new file mode 100644
index 0000000000..ac2d63a4d3
--- /dev/null
+++ b/lib/memarea/rte_memarea.h
@@ -0,0 +1,136 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 HiSilicon Limited
+ */
+
+#ifndef RTE_MEMAREA_H
+#define RTE_MEMAREA_H
+
+/**
+ * @file
+ * RTE Memarea.
+ *
+ * The memarea is an allocator of variable-size object which based on a memory
+ * region. It has the following features:
+ *
+ * - The allocated object aligned at RTE_CACHE_LINE_SIZE default.
+ *
+ * - The memory region can be initialized from the following memory sources:
+ *   1. HEAP: e.g. invoke rte_malloc_socket.
+ *   2. LIBC: e.g. invoke posix_memalign.
+ *   3. User memory: it can be from e.g. rte_extmem_xxx as long as it is
+ *      available. The memory's start address must be aligned to
+ *      RTE_CACHE_LINE_SIZE.
+ *   4. Another memarea: it can be allocated from another memarea.
+ *
+ * - It provides refcnt feature which could be useful in multi-reader scenario.
+ *
+ * - It supports MT-safe as long as it's specified at creation time. If not
+ *   specified, all the functions of the memarea API are lock-free, and assume
+ *   to not be invoked in parallel on different logical cores to work on the
+ *   same memarea.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <rte_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTE_MEMAREA_NAMESIZE	64
+
+/**
+ * Memarea memory source.
+ */
+enum rte_memarea_source {
+	/** Memory source comes from rte memory. */
+	RTE_MEMAREA_SOURCE_HEAP,
+	/** Memory source comes from libc. */
+	RTE_MEMAREA_SOURCE_LIBC,
+	/** Memory source comes from user memory. */
+	RTE_MEMAREA_SOURCE_USER,
+	/** Memory source comes from another memarea. */
+	RTE_MEMAREA_SOURCE_MEMAREA,
+};
+
+/**
+ * Memarea memory management algorithm.
+ */
+enum rte_memarea_alg {
+	/** The default management algorithm is a variant of the next fit
+	 * algorithm. It uses a free-list to apply for memory and uses an
+	 * element-list in ascending order of address to support merging
+	 * upon free.
+	 */
+	RTE_MEMAREA_ALG_NEXTFIT,
+};
+
+struct rte_memarea;
+
+/**
+ * Memarea creation parameters.
+ */
+struct rte_memarea_param {
+	char name[RTE_MEMAREA_NAMESIZE]; /**< Name of memarea. */
+	enum rte_memarea_source source;  /**< Memory source of memarea. */
+	enum rte_memarea_alg alg;        /**< Memory management algorithm. */
+	size_t total_sz;                 /**< total size (bytes) of memarea. */
+	/** Indicates whether the memarea API should be MT-safe. */
+	uint32_t mt_safe : 1;
+	union {
+		/** Numa socket from which to apply for memarea's memory, this
+		 * field is valid only when the source is set to be
+		 * RTE_MEMAREA_SOURCE_HEAP.
+		 */
+		int numa_socket;
+		/** User memory address, this field is valid only when the
+		 * source is set to be RTE_MEMAREA_SOURCE_USER.
+		 * Note: the address must align at least RTE_CACHE_LINE_SIZE.
+		 */
+		void *user_addr;
+		/** Source memarea, this field is valid only when the source is
+		 * set to be RTE_MEMAREA_SOURCE_MEMAREA.
+		 */
+		struct rte_memarea *src_memarea;
+	};
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create memarea.
+ *
+ * Create one new memarea.
+ *
+ * @param init
+ *   The init parameter of memarea.
+ *
+ * @return
+ *   Non-NULL on success. Otherwise NULL is returned.
+ */
+__rte_experimental
+struct rte_memarea *rte_memarea_create(const struct rte_memarea_param *init);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy memarea.
+ *
+ * Destroy the memarea.
+ *
+ * @param ma
+ *   The pointer of memarea.
+ */
+__rte_experimental
+void rte_memarea_destroy(struct rte_memarea *ma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_MEMAREA_H */
diff --git a/lib/memarea/version.map b/lib/memarea/version.map
new file mode 100644
index 0000000000..f36a04d7cf
--- /dev/null
+++ b/lib/memarea/version.map
@@ -0,0 +1,12 @@ 
+EXPERIMENTAL {
+	global:
+
+	rte_memarea_create;
+	rte_memarea_destroy;
+
+	local: *;
+};
+
+INTERNAL {
+	local: *;
+};
diff --git a/lib/meson.build b/lib/meson.build
index c51cdc24fa..87d621e792 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -42,6 +42,7 @@  libraries = [
         'kni',
         'latencystats',
         'lpm',
+        'memarea',
         'member',
         'pcapng',
         'power',