The memarea library is an allocator of variable-size object. It is a
collection of allocated objects that can be efficiently alloc or free
all at once, the main features are as follows:
a) it facilitate alloc and free of memory with low overhead.

b) it provides refcnt feature which could be useful in some scenes.

c) it supports MT-safe as long as it's specified at creation time.

d) it's memory source could comes from:
d.1) system API: malloc in C library.
d.2) user provided address: it can be from the rte_malloc API series
or extended memory as long as it is available.
d.3) user provided memarea: it can be from another memarea.

This patch provides create/destroy API.

Signed-off-by: Chengwen Feng <fengcheng...@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  |  41 ++++++++
 doc/guides/rel_notes/release_22_11.rst |   6 ++
 lib/eal/include/rte_log.h              |   1 +
 lib/memarea/memarea_private.h          |  30 ++++++
 lib/memarea/meson.build                |  16 +++
 lib/memarea/rte_memarea.c              | 140 +++++++++++++++++++++++++
 lib/memarea/rte_memarea.h              | 131 +++++++++++++++++++++++
 lib/memarea/version.map                |  12 +++
 lib/meson.build                        |   1 +
 13 files changed, 387 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

diff --git a/MAINTAINERS b/MAINTAINERS
index 32ffdd1a61..92e77f1318 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1557,6 +1557,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 <fengcheng...@huawei.com>
+F: lib/memarea
+F: doc/guides/prog_guide/memarea_lib.rst
+
 Membership - EXPERIMENTAL
 M: Yipeng Wang <yipeng1.w...@intel.com>
 M: Sameh Gobriel <sameh.gobr...@intel.com>
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 186a258be4..25dbef0b68 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -64,7 +64,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 608494a7c0..bdc5d2b0d5 100644
--- a/doc/api/doxy-api.conf.in
+++ b/doc/api/doxy-api.conf.in
@@ -55,6 +55,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..1979f0a12c
--- /dev/null
+++ b/doc/guides/prog_guide/memarea_lib.rst
@@ -0,0 +1,41 @@
+..  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:
+
+* It facilitate alloc and free of memory with low overhead.
+
+* It's memory source could comes from: 1) System API: e.g. malloc/memalign in
+  C library. 2) User provided address: it can be from the rte_malloc API series
+  or extended memory as long as it is available. 3) User provided memarea: it
+  can be from another memarea.
+
+* The default aligement size is ``RTE_CACHE_LINE_SIZE``.
+
+* It provides refcnt feature which could be useful in some scenes.
+
+* 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 object, 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 object.
+
+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 8c021cf050..1cf522132c 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -55,6 +55,12 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **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.
+
 
 Removed Items
 -------------
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..94931b46e9
--- /dev/null
+++ b/lib/memarea/memarea_private.h
@@ -0,0 +1,30 @@
+/* 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_FREE_ELEM_COOKIE       0xFFFFFFFF
+
+struct memarea_elem {
+       size_t   size;
+       uint32_t cookie;
+       int32_t  refcnt; /* Non-zero indicates that it has been allocated */
+       TAILQ_ENTRY(memarea_elem) elem_node;
+       TAILQ_ENTRY(memarea_elem) free_node;
+} __rte_cache_aligned;
+
+TAILQ_HEAD(memarea_elem_list, memarea_elem);
+
+struct memarea_private {
+       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..3f535d315f
--- /dev/null
+++ b/lib/memarea/rte_memarea.c
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 HiSilicon Limited
+ */
+
+#include <stdio.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_memarea.h>
+#include <rte_spinlock.h>
+
+#include "memarea_private.h"
+
+static int
+memarea_check_param(const struct rte_memarea_param *init)
+{
+       size_t len;
+
+       len = strnlen(init->name, RTE_MEMAREA_NAMESIZE);
+       if (len == 0 || len >= RTE_MEMAREA_NAMESIZE) {
+               RTE_LOG(ERR, MEMAREA, "memarea name invalid!\n");
+               return -EINVAL;
+       }
+
+       if (init->source >= RTE_MEMAREA_SOURCE_BUTT) {
+               RTE_LOG(ERR, MEMAREA, "memarea source invalid!\n");
+               return -EINVAL;
+       }
+
+       if (init->total_sz <= sizeof(struct memarea_elem)) {
+               RTE_LOG(ERR, MEMAREA, "memarea total size invalid!\n");
+               return -EINVAL;
+       }
+
+       if (init->source == RTE_MEMAREA_SOURCE_USER_ADDR && init->user_addr == 
NULL) {
+               RTE_LOG(ERR, MEMAREA, "memarea user provided addr invalid!\n");
+               return -EINVAL;
+       }
+
+       if (init->source == RTE_MEMAREA_SOURCE_USER_ADDR &&
+           ((uintptr_t)init->user_addr & (RTE_CACHE_LINE_SIZE - 1))) {
+               RTE_LOG(ERR, MEMAREA, "memarea user provided addr align 
invalid!\n");
+               return -EINVAL;
+       }
+
+       if (init->source == RTE_MEMAREA_SOURCE_USER_MEMAREA && 
init->user_memarea == NULL) {
+               RTE_LOG(ERR, MEMAREA, "memarea user provided memarea 
invalid!\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void *
+memarea_alloc_from_system_api(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_SYSTEM_API)
+               ptr = memarea_alloc_from_system_api(init->total_sz);
+       else if (init->source == RTE_MEMAREA_SOURCE_USER_ADDR)
+               ptr = init->user_addr;
+
+       if (ptr == NULL)
+               RTE_LOG(ERR, MEMAREA, "memarea alloc memory area fail!\n");
+
+       return ptr;
+}
+
+struct rte_memarea *
+rte_memarea_create(const struct rte_memarea_param *init)
+{
+       struct memarea_private *priv;
+       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);
+       priv = rte_zmalloc(NULL, sizeof(struct memarea_private), 
RTE_CACHE_LINE_SIZE);
+       if (ma == NULL || priv == NULL) {
+               RTE_LOG(ERR, MEMAREA, "malloc memarea management obj fail!\n");
+               rte_free(ma);
+               rte_free(priv);
+               return NULL;
+       }
+
+       ma->private_data = priv;
+       priv->init = *init;
+       rte_spinlock_init(&priv->lock);
+       TAILQ_INIT(&priv->elem_list);
+       TAILQ_INIT(&priv->free_list);
+       priv->area_addr = addr;
+       elem = addr;
+       elem->size = init->total_sz - sizeof(struct memarea_elem);
+       elem->cookie = MEMAREA_FREE_ELEM_COOKIE;
+       elem->refcnt = 0;
+       TAILQ_INSERT_TAIL(&priv->elem_list, elem, elem_node);
+       TAILQ_INSERT_TAIL(&priv->free_list, elem, free_node);
+
+       return ma;
+}
+
+static void
+memarea_free_area(struct memarea_private *priv)
+{
+       if (priv->init.source == RTE_MEMAREA_SOURCE_SYSTEM_API)
+               free(priv->area_addr);
+}
+
+void
+rte_memarea_destroy(struct rte_memarea *ma)
+{
+       if (ma == NULL)
+               return;
+       memarea_free_area(ma->private_data);
+       rte_free(ma->private_data);
+       rte_free(ma);
+}
diff --git a/lib/memarea/rte_memarea.h b/lib/memarea/rte_memarea.h
new file mode 100644
index 0000000000..ddca0a47e2
--- /dev/null
+++ b/lib/memarea/rte_memarea.h
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 HiSilicon Limited
+ */
+
+#ifndef RTE_MEMAREA_H
+#define RTE_MEMAREA_H
+
+/**
+ * @file
+ * RTE Memarea.
+ *
+ * A memory area is an allocator of variable-size object. It is identified
+ * by its name.
+ *
+ * The memarea is a collection of allocated objects that can be efficiently
+ * alloc or free all at once, the main feature are as follows:
+ *   a) It facilitate alloc and free of memory with low overhead.
+ *   b) It's memory source could comes from:
+ *      1) System API: malloc/memalign in C library.
+ *      2) User provided address: it can be from the rte_malloc API series
+ *         or extended memory as long as it is available. The address must be
+ *         aligned to RTE_CACHE_LINE_SIZE.
+ *      3) User provided memarea: it can be from another memarea. So we can
+ *         build the following memory management structure:
+ *         \code{.unparsed}
+ *                           -------------
+ *                           | memarea-1 |
+ *                           -------------
+ *                                 |
+ *                                 v
+ *                  ------------------------------
+ *                  |               |            |
+ *                  v               v            v
+ *            -------------   -------------   -------
+ *            | memarea-2 |   | memarea-3 |   | obj |
+ *            -------------   -------------   -------
+ *         \endcode
+ *   c) The default alignment size is RTE_CACHE_LINE_SIZE.
+ *   d) It provides refcnt feature which could be useful in some scenes.
+ *   e) 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 object.
+ */
+
+#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 system API (e.g. malloc). */
+       RTE_MEMAREA_SOURCE_SYSTEM_API,
+       /** Memory source comes from user-provided address. */
+       RTE_MEMAREA_SOURCE_USER_ADDR,
+       /** Memory source comes from user-provided memarea. */
+       RTE_MEMAREA_SOURCE_USER_MEMAREA,
+
+       RTE_MEMAREA_SOURCE_BUTT
+};
+
+struct rte_memarea {
+       void *private_data; /**< private management data pointer. */
+};
+
+struct rte_memarea_param {
+       char name[RTE_MEMAREA_NAMESIZE]; /**< Name of memarea. */
+       enum rte_memarea_source source;  /**< Memory source of memarea. */
+       size_t total_sz;                 /**< total size (bytes) of memarea. */
+       /** Indicates whether the memarea API should be MT-safe. */
+       uint32_t mt_safe : 1;
+       union {
+               /** User provided address, this field is valid only when the
+                * source is set to be RTE_MEMAREA_SOURCE_USER_ADDR.
+                * Note: the provided address must align at least
+                * RTE_CACHE_LINE_SIZE.
+                */
+               void *user_addr;
+               /** User provided memarea, this field is valid only when the
+                * source is set to be RTE_MEMAREA_SOURCE_USER_MEMAREA.
+                */
+               struct rte_memarea *user_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 c648f7d800..521a25d6c0 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -42,6 +42,7 @@ libraries = [
         'kni',
         'latencystats',
         'lpm',
+        'memarea',
         'member',
         'pcapng',
         'power',
-- 
2.17.1

Reply via email to