From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 46D86A00C3; Tue, 20 Sep 2022 05:53:07 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5945340DFB; Tue, 20 Sep 2022 05:53:02 +0200 (CEST) Received: from szxga03-in.huawei.com (szxga03-in.huawei.com [45.249.212.189]) by mails.dpdk.org (Postfix) with ESMTP id 42F3A4069B for ; Tue, 20 Sep 2022 05:53:00 +0200 (CEST) Received: from dggpeml500024.china.huawei.com (unknown [172.30.72.56]) by szxga03-in.huawei.com (SkyGuard) with ESMTP id 4MWndP2XhvzHp0W; Tue, 20 Sep 2022 11:50:49 +0800 (CST) Received: from localhost.localdomain (10.67.165.24) by dggpeml500024.china.huawei.com (7.185.36.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.31; Tue, 20 Sep 2022 11:52:57 +0800 From: Chengwen Feng To: CC: , , , Subject: [PATCH 1/8] memarea: introduce memory area library Date: Tue, 20 Sep 2022 03:46:36 +0000 Message-ID: <20220920034643.55476-2-fengchengwen@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220920034643.55476-1-fengchengwen@huawei.com> References: <20220721044648.6817-1-fengchengwen@huawei.com> <20220920034643.55476-1-fengchengwen@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.67.165.24] X-ClientProxiedBy: dggems705-chm.china.huawei.com (10.3.19.182) To dggpeml500024.china.huawei.com (7.185.36.10) X-CFilter-Loop: Reflected X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org 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 --- 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 +F: lib/memarea +F: doc/guides/prog_guide/memarea_lib.rst + Membership - EXPERIMENTAL M: Yipeng Wang M: Sameh Gobriel 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 + +#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 + +#include +#include +#include +#include +#include + +#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 +#include +#include + +#include + +#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