@@ -1558,6 +1558,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>
@@ -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),
@@ -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 \
@@ -37,6 +37,7 @@ Programmer's Guide
hash_lib
toeplitz_hash_lib
efd_lib
+ memarea_lib
member_lib
lpm_lib
lpm6_lib
new file mode 100644
@@ -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
@@ -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
-------------
@@ -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. */
new file mode 100644
@@ -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 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 */
new file mode 100644
@@ -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 += []
new file mode 100644
@@ -0,0 +1,144 @@
+/* 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_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_SYSTEM_API &&
+ init->source != RTE_MEMAREA_SOURCE_USER_ADDR &&
+ init->source != RTE_MEMAREA_SOURCE_USER_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_ADDR && init->user_addr == NULL) {
+ RTE_LOG(ERR, MEMAREA, "memarea: %s user provided addr is NULL!\n", init->name);
+ 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: %s user provided addr should align: %d!\n",
+ init->name, RTE_CACHE_LINE_SIZE);
+ return -EINVAL;
+ }
+
+ if (init->source == RTE_MEMAREA_SOURCE_USER_MEMAREA && init->user_memarea == NULL) {
+ RTE_LOG(ERR, MEMAREA, "memarea: %s user provided memarea is NULL!\n", init->name);
+ 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: %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;
+ elem->size = init->total_sz - sizeof(struct memarea_elem);
+ elem->cookie = MEMAREA_FREE_ELEM_COOKIE;
+ elem->refcnt = 0;
+ TAILQ_INSERT_TAIL(&ma->elem_list, elem, elem_node);
+ TAILQ_INSERT_TAIL(&ma->free_list, elem, free_node);
+
+ return ma;
+}
+
+static void
+memarea_free_area(struct rte_memarea *ma)
+{
+ if (ma->init.source == RTE_MEMAREA_SOURCE_SYSTEM_API)
+ free(ma->area_addr);
+}
+
+void
+rte_memarea_destroy(struct rte_memarea *ma)
+{
+ if (ma == NULL)
+ return;
+ memarea_free_area(ma);
+ rte_free(ma);
+}
new file mode 100644
@@ -0,0 +1,127 @@
+/* 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,
+};
+
+struct rte_memarea;
+
+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 */
new file mode 100644
@@ -0,0 +1,12 @@
+EXPERIMENTAL {
+ global:
+
+ rte_memarea_create;
+ rte_memarea_destroy;
+
+ local: *;
+};
+
+INTERNAL {
+ local: *;
+};
@@ -42,6 +42,7 @@ libraries = [
'kni',
'latencystats',
'lpm',
+ 'memarea',
'member',
'pcapng',
'power',