From patchwork Mon Oct 17 03:40:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: fengchengwen X-Patchwork-Id: 118236 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id BBD7AA0556; Mon, 17 Oct 2022 05:47:08 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2146241148; Mon, 17 Oct 2022 05:46:53 +0200 (CEST) Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) by mails.dpdk.org (Postfix) with ESMTP id E94934021E for ; Mon, 17 Oct 2022 05:46:47 +0200 (CEST) Received: from dggpeml500024.china.huawei.com (unknown [172.30.72.55]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4MrN8r2XyKzmVT8; Mon, 17 Oct 2022 11:42:04 +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; Mon, 17 Oct 2022 11:46:45 +0800 From: Chengwen Feng To: , , , , , CC: , Subject: [PATCH v10 1/7] memarea: introduce memarea library Date: Mon, 17 Oct 2022 03:40:52 +0000 Message-ID: <20221017034058.34176-2-fengchengwen@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221017034058.34176-1-fengchengwen@huawei.com> References: <20220721044648.6817-1-fengchengwen@huawei.com> <20221017034058.34176-1-fengchengwen@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.165.24] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) 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 which based on a memory region. This patch provides rte_memarea_create() and rte_memarea_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 | 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 | 10 ++ lib/memarea/rte_memarea.c | 158 +++++++++++++++++++++++++ lib/memarea/rte_memarea.h | 124 +++++++++++++++++++ lib/memarea/version.map | 12 ++ lib/meson.build | 1 + 14 files changed, 394 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 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 +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 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..d032b24ce9 --- /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, providing 'region-based memory +management' function [1]. + +The main features are as follows: + +* The memory region can be initialized from the following memory sources: + + - HEAP: e.g. invoke ``rte_malloc_socket``. + + - LIBC: e.g. invoke posix_memalign. + + - 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..f8e3a23db7 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, providing '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 + +#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..d5c2c442f5 --- /dev/null +++ b/lib/memarea/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2022 HiSilicon Limited + +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..41e5c007c2 --- /dev/null +++ b/lib/memarea/rte_memarea.c @@ -0,0 +1,158 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 HiSilicon Limited + */ + +#include +#include + +#include +#include +#include +#include + +#include "rte_memarea.h" +#include "memarea_private.h" + +static int +memarea_check_param(const struct rte_memarea_param *init) +{ +#define MEMAREA_MIN_SIZE 1024 + 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_MEMAREA) { + RTE_LOG(ERR, MEMAREA, "memarea: %s source: %d not supported!\n", + init->name, init->source); + return -EINVAL; + } + + if (init->total_sz < MEMAREA_MIN_SIZE) { + 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_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) +{ +#ifndef RTE_EXEC_ENV_WINDOWS + void *ptr = NULL; + int ret; + ret = posix_memalign(&ptr, RTE_CACHE_LINE_SIZE, size); + if (ret) + return NULL; + return ptr; +#else + /* Windows platform don't support posix_memalign() */ + return malloc(size); +#endif +} + +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); + + 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; + size_t unaligns; + 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; + /* The address returned by the windows platform may not be cache-line aligned. + * The elem address and total_sz are adjusted. + */ + unaligns = ((uintptr_t)addr) & (RTE_CACHE_LINE_SIZE - 1); + if (unaligns > 0) { + elem = RTE_PTR_ADD(addr, RTE_CACHE_LINE_SIZE - unaligns); + ma->init.total_sz -= (RTE_CACHE_LINE_SIZE - unaligns); + } else { + 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..d48ceaf733 --- /dev/null +++ b/lib/memarea/rte_memarea.h @@ -0,0 +1,124 @@ +/* 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 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. 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 +#include +#include + +#include + +#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 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; + /** 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', From patchwork Mon Oct 17 03:40:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: fengchengwen X-Patchwork-Id: 118234 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id B3F22A0556; Mon, 17 Oct 2022 05:46:57 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3012B40E5A; Mon, 17 Oct 2022 05:46:51 +0200 (CEST) Received: from szxga03-in.huawei.com (szxga03-in.huawei.com [45.249.212.189]) by mails.dpdk.org (Postfix) with ESMTP id E67BD40143 for ; Mon, 17 Oct 2022 05:46:47 +0200 (CEST) Received: from dggpeml500024.china.huawei.com (unknown [172.30.72.55]) by szxga03-in.huawei.com (SkyGuard) with ESMTP id 4MrNCD59qWzJn2L; Mon, 17 Oct 2022 11:44:08 +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; Mon, 17 Oct 2022 11:46:45 +0800 From: Chengwen Feng To: , , , , , CC: , Subject: [PATCH v10 2/7] test/memarea: support memarea test Date: Mon, 17 Oct 2022 03:40:53 +0000 Message-ID: <20221017034058.34176-3-fengchengwen@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221017034058.34176-1-fengchengwen@huawei.com> References: <20220721044648.6817-1-fengchengwen@huawei.com> <20221017034058.34176-1-fengchengwen@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.165.24] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) 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 This patch supports memarea test of rte_memarea_create() and rte_memarea_destroy() API. Signed-off-by: Chengwen Feng --- MAINTAINERS | 1 + app/test/meson.build | 2 + app/test/test_memarea.c | 130 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 app/test/test_memarea.c diff --git a/MAINTAINERS b/MAINTAINERS index 3d8d4c2dbe..38625ae1be 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1555,6 +1555,7 @@ Memarea - EXPERIMENTAL M: Chengwen Feng F: lib/memarea F: doc/guides/prog_guide/memarea_lib.rst +F: app/test/test_memarea* Membership - EXPERIMENTAL M: Yipeng Wang diff --git a/app/test/meson.build b/app/test/meson.build index 396b133959..8943f24668 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -84,6 +84,7 @@ test_sources = files( 'test_malloc.c', 'test_malloc_perf.c', 'test_mbuf.c', + 'test_memarea.c', 'test_member.c', 'test_member_perf.c', 'test_memcpy.c', @@ -200,6 +201,7 @@ fast_tests = [ ['malloc_autotest', false, true], ['mbuf_autotest', false, true], ['mcslock_autotest', false, true], + ['memarea_autotest', true, true], ['memcpy_autotest', true, true], ['memory_autotest', false, true], ['mempool_autotest', false, true], diff --git a/app/test/test_memarea.c b/app/test/test_memarea.c new file mode 100644 index 0000000000..cfd50de45f --- /dev/null +++ b/app/test/test_memarea.c @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 HiSilicon Limited + */ + +#include +#include + +#include "test.h" + +#include +#include + +#define MEMAREA_TEST_DEFAULT_SIZE 0x1000 + +#define MEMAREA_TEST_API_RUN(test_func) \ + do { \ + int ret = test_func(); \ + if (ret < 0) { \ + printf("%s Failed\n", #test_func); \ + fails++; \ + } else { \ + printf("%s Passed\n", #test_func); \ + } \ + } while (0) + +static int fails; + +static void +test_memarea_prepare(void) +{ + fails = 0; +} + +static int +test_memarea_retcode(void) +{ + return fails > 0 ? -1 : 0; +} + +static void +test_memarea_init_param(struct rte_memarea_param *init) +{ + memset(init, 0, sizeof(struct rte_memarea_param)); + sprintf(init->name, "%s", "test-memarea"); + init->source = RTE_MEMAREA_SOURCE_LIBC; + init->total_sz = MEMAREA_TEST_DEFAULT_SIZE; + init->mt_safe = 1; +} + +static int +test_memarea_create_bad_param(void) +{ + struct rte_memarea_param init; + struct rte_memarea *ma; + + /* test for NULL */ + ma = rte_memarea_create(NULL); + RTE_TEST_ASSERT(ma == NULL, "Expected NULL"); + + /* test for invalid name */ + memset(&init, 0, sizeof(init)); + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma == NULL, "Expected NULL"); + memset(&init.name, 1, sizeof(init.name)); + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma == NULL, "Expected NULL"); + + /* test for invalid source */ + test_memarea_init_param(&init); + init.source = RTE_MEMAREA_SOURCE_MEMAREA + 1; + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma == NULL, "Expected NULL"); + + /* test for total_sz */ + test_memarea_init_param(&init); + init.total_sz = 0; + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma == NULL, "Expected NULL"); + + /* test for memarea NULL */ + test_memarea_init_param(&init); + init.source = RTE_MEMAREA_SOURCE_MEMAREA; + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma == NULL, "Expected NULL"); + + /* test for alg invalid */ + test_memarea_init_param(&init); + init.alg = RTE_MEMAREA_ALG_NEXTFIT + 1; + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma == NULL, "Expected NULL"); + + return 0; +} + +static int +test_memarea_create_destroy(void) +{ + struct rte_memarea_param init; + struct rte_memarea *ma; + + /* test for create with HEAP */ + test_memarea_init_param(&init); + init.source = RTE_MEMAREA_SOURCE_HEAP; + init.numa_socket = SOCKET_ID_ANY; + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma != NULL, "Expected Non-NULL"); + rte_memarea_destroy(ma); + + /* test for create with LIBC */ + test_memarea_init_param(&init); + init.source = RTE_MEMAREA_SOURCE_LIBC; + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma != NULL, "Expected Non-NULL"); + rte_memarea_destroy(ma); + + return 0; +} + +static int +test_memarea(void) +{ + test_memarea_prepare(); + + MEMAREA_TEST_API_RUN(test_memarea_create_bad_param); + MEMAREA_TEST_API_RUN(test_memarea_create_destroy); + + return test_memarea_retcode(); +} + +REGISTER_TEST_COMMAND(memarea_autotest, test_memarea); From patchwork Mon Oct 17 03:40:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: fengchengwen X-Patchwork-Id: 118235 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 04169A0556; Mon, 17 Oct 2022 05:47:03 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 12129410F9; Mon, 17 Oct 2022 05:46:52 +0200 (CEST) Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) by mails.dpdk.org (Postfix) with ESMTP id E0B1B400D7 for ; Mon, 17 Oct 2022 05:46:47 +0200 (CEST) Received: from dggpeml500024.china.huawei.com (unknown [172.30.72.55]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4MrN900KvNzVjs4; Mon, 17 Oct 2022 11:42:12 +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; Mon, 17 Oct 2022 11:46:45 +0800 From: Chengwen Feng To: , , , , , CC: , Subject: [PATCH v10 3/7] memarea: support alloc/free/refcnt-update API Date: Mon, 17 Oct 2022 03:40:54 +0000 Message-ID: <20221017034058.34176-4-fengchengwen@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221017034058.34176-1-fengchengwen@huawei.com> References: <20220721044648.6817-1-fengchengwen@huawei.com> <20221017034058.34176-1-fengchengwen@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.165.24] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) 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 This patch supports rte_memarea_alloc()/rte_memarea_free()/ rte_memarea_refcnt_update() API. Signed-off-by: Chengwen Feng --- doc/guides/prog_guide/memarea_lib.rst | 10 ++ lib/memarea/memarea_private.h | 3 + lib/memarea/rte_memarea.c | 157 ++++++++++++++++++++++++++ lib/memarea/rte_memarea.h | 74 ++++++++++++ lib/memarea/version.map | 3 + 5 files changed, 247 insertions(+) diff --git a/doc/guides/prog_guide/memarea_lib.rst b/doc/guides/prog_guide/memarea_lib.rst index d032b24ce9..8fbfd06a5d 100644 --- a/doc/guides/prog_guide/memarea_lib.rst +++ b/doc/guides/prog_guide/memarea_lib.rst @@ -33,6 +33,16 @@ returns the pointer to the created memarea or ``NULL`` if the creation failed. The ``rte_memarea_destroy()`` function is used to destroy a memarea. +The ``rte_memarea_alloc()`` function is used to alloc one memory object from +the memarea. + +The ``rte_memarea_free()`` function is used to free one memory object which +allocated by ``rte_memarea_alloc()``. + +The ``rte_memarea_refcnt_update()`` function is used to update the memory +object's reference count, if the count reaches zero, the memory object will +be freed to memarea. + Reference --------- diff --git a/lib/memarea/memarea_private.h b/lib/memarea/memarea_private.h index 59be9c1d00..f5accf2987 100644 --- a/lib/memarea/memarea_private.h +++ b/lib/memarea/memarea_private.h @@ -28,6 +28,9 @@ struct rte_memarea { void *area_addr; struct memarea_elem_list elem_list; struct memarea_elem_list free_list; + + uint64_t alloc_fails; + uint64_t refcnt_check_fails; } __rte_cache_aligned; #endif /* MEMAREA_PRIVATE_H */ diff --git a/lib/memarea/rte_memarea.c b/lib/memarea/rte_memarea.c index 41e5c007c2..a0935dafb6 100644 --- a/lib/memarea/rte_memarea.c +++ b/lib/memarea/rte_memarea.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -84,6 +85,8 @@ memarea_alloc_area(const struct rte_memarea_param *init) 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_MEMAREA) + ptr = rte_memarea_alloc(init->src_memarea, init->total_sz, 0); if (ptr == NULL) RTE_LOG(ERR, MEMAREA, "memarea: %s alloc memory area fail!\n", init->name); @@ -146,6 +149,8 @@ memarea_free_area(struct rte_memarea *ma) rte_free(ma->area_addr); else if (ma->init.source == RTE_MEMAREA_SOURCE_LIBC) free(ma->area_addr); + else if (ma->init.source == RTE_MEMAREA_SOURCE_MEMAREA) + rte_memarea_free(ma->init.src_memarea, ma->area_addr); } void @@ -156,3 +161,155 @@ rte_memarea_destroy(struct rte_memarea *ma) memarea_free_area(ma); rte_free(ma); } + +static inline void +memarea_lock(struct rte_memarea *ma) +{ + if (ma->init.mt_safe) + rte_spinlock_lock(&ma->lock); +} + +static inline void +memarea_unlock(struct rte_memarea *ma) +{ + if (ma->init.mt_safe) + rte_spinlock_unlock(&ma->lock); +} + +static inline bool +memarea_whether_add_node(size_t free_size, size_t need_size) +{ + size_t align_size = RTE_ALIGN_CEIL(need_size, RTE_CACHE_LINE_SIZE); + return free_size > align_size && (free_size - align_size) > sizeof(struct memarea_elem); +} + +static inline void +memarea_add_node(struct rte_memarea *ma, struct memarea_elem *elem, size_t need_size) +{ + size_t align_size = RTE_ALIGN_CEIL(need_size, RTE_CACHE_LINE_SIZE); + struct memarea_elem *new_elem; + + new_elem = (struct memarea_elem *)RTE_PTR_ADD(elem, sizeof(struct memarea_elem) + + align_size); + new_elem->size = elem->size - align_size - sizeof(struct memarea_elem); + new_elem->magic = MEMAREA_AVAILABLE_ELEM_MAGIC; + new_elem->cookie = MEMAREA_AVAILABLE_ELEM_COOKIE; + new_elem->refcnt = 0; + TAILQ_INSERT_AFTER(&ma->elem_list, elem, new_elem, elem_node); + TAILQ_INSERT_AFTER(&ma->free_list, elem, new_elem, free_node); + elem->size = align_size; +} + +void * +rte_memarea_alloc(struct rte_memarea *ma, size_t size, uint32_t cookie) +{ + struct memarea_elem *elem; + void *ptr = NULL; + + if (unlikely(ma == NULL || size == 0)) + return NULL; + + memarea_lock(ma); + TAILQ_FOREACH(elem, &ma->free_list, free_node) { + if (unlikely(elem->magic != MEMAREA_AVAILABLE_ELEM_MAGIC)) + break; + if (elem->size < size) + continue; + if (memarea_whether_add_node(elem->size, size)) + memarea_add_node(ma, elem, size); + elem->magic = MEMAREA_ALLOCATED_ELEM_MAGIC; + elem->cookie = cookie; + elem->refcnt = 1; + TAILQ_REMOVE(&ma->free_list, elem, free_node); + ptr = RTE_PTR_ADD(elem, sizeof(struct memarea_elem)); + break; + } + if (unlikely(ptr == NULL)) + ma->alloc_fails++; + memarea_unlock(ma); + + return ptr; +} + +void +rte_memarea_free(struct rte_memarea *ma, void *ptr) +{ + if (unlikely(ma == NULL || ptr == NULL)) + return; + + rte_memarea_refcnt_update(ma, ptr, -1); +} + +static inline void +memarea_merge_node(struct rte_memarea *ma, struct memarea_elem *curr, + struct memarea_elem *next, bool del_next_from_free, + bool add_curr_to_free) +{ + curr->size += next->size + sizeof(struct memarea_elem); + next->size = 0; + next->magic = 0; + next->cookie = 0; + TAILQ_REMOVE(&ma->elem_list, next, elem_node); + if (del_next_from_free) + TAILQ_REMOVE(&ma->free_list, next, free_node); + if (add_curr_to_free) { + curr->magic = MEMAREA_AVAILABLE_ELEM_MAGIC; + curr->cookie = MEMAREA_AVAILABLE_ELEM_COOKIE; + TAILQ_INSERT_TAIL(&ma->free_list, curr, free_node); + } +} + +static inline void +memarea_free_elem(struct rte_memarea *ma, struct memarea_elem *elem) +{ + struct memarea_elem *prev, *next; + bool merged = false; + + prev = TAILQ_PREV(elem, memarea_elem_list, elem_node); + next = TAILQ_NEXT(elem, elem_node); + if (prev != NULL && prev->refcnt == 0) { + memarea_merge_node(ma, prev, elem, false, false); + elem = prev; + merged = true; + } + if (next != NULL && next->refcnt == 0) { + memarea_merge_node(ma, elem, next, true, !merged); + merged = true; + } + if (!merged) { + elem->magic = MEMAREA_AVAILABLE_ELEM_MAGIC; + elem->cookie = MEMAREA_AVAILABLE_ELEM_COOKIE; + TAILQ_INSERT_TAIL(&ma->free_list, elem, free_node); + } +} + +void +rte_memarea_refcnt_update(struct rte_memarea *ma, void *ptr, int32_t value) +{ + struct memarea_elem *elem = (struct memarea_elem *)RTE_PTR_SUB(ptr, + sizeof(struct memarea_elem)); + + memarea_lock(ma); + if (unlikely(elem->magic != MEMAREA_ALLOCATED_ELEM_MAGIC)) { + RTE_LOG(ERR, MEMAREA, "memarea: %s magic: 0x%x check fail!\n", + ma->init.name, elem->magic); + memarea_unlock(ma); + return; + } + + if (unlikely(elem->refcnt <= 0 || elem->refcnt + value < 0)) { + RTE_LOG(ERR, MEMAREA, + "memarea: %s cookie: 0x%x curr refcnt: %d update refcnt: %d check fail!\n", + ma->init.name, elem->cookie, elem->refcnt, value); + ma->refcnt_check_fails++; + if (elem->refcnt > 0) + elem->refcnt += value; + memarea_unlock(ma); + return; + } + + elem->refcnt += value; + if (elem->refcnt == 0) + memarea_free_elem(ma, elem); + memarea_unlock(ma); +} diff --git a/lib/memarea/rte_memarea.h b/lib/memarea/rte_memarea.h index d48ceaf733..31c499ec07 100644 --- a/lib/memarea/rte_memarea.h +++ b/lib/memarea/rte_memarea.h @@ -117,6 +117,80 @@ struct rte_memarea *rte_memarea_create(const struct rte_memarea_param *init); __rte_experimental void rte_memarea_destroy(struct rte_memarea *ma); +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Allocate memory from memarea. + * + * Allocate one memory object from the memarea. + * + * @param ma + * The pointer of memarea. + * @param size + * The memory size to be allocated. + * @param cookie + * User-provided footprint which could used to debug memory leak. + * + * @return + * - NULL on error. Not enough memory, or invalid arguments (ma is NULL, + * size is 0). + * - Otherwise, the pointer to the allocated object. + */ +__rte_experimental +void *rte_memarea_alloc(struct rte_memarea *ma, size_t size, uint32_t cookie); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Free memory to memarea. + * + * Free one memory object to the memarea. If the object's refcnt is greater + * than one, only the refcnt is decremented by one. Otherwise the object is + * released. + * @note The memory object must have been returned by a previous call to + * rte_memarea_alloc(), if it is allocated from memarea-A, it must be freed to + * the same memarea-A. The behaviour of rte_memarea_free() is undefined if the + * memarea or pointer does not match these requirements. + * + * @param ma + * The pointer of memarea. If the ma is NULL, the function does nothing. + * @param ptr + * The pointer of memory object which need be freed. If the pointer is NULL, + * the function does nothing. + */ +__rte_experimental +void rte_memarea_free(struct rte_memarea *ma, void *ptr); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Update memory's refcnt. + * + * Update one memory object's refcnt. When refcnt is updated to be zero, the + * memory object is freed. + * + * @note The memory object must have been returned by a previous call to + * rte_memarea_alloc(), if it is allocated from memarea-A, the refcnt update + * must be operated to the same memarea-A. The behaviour of + * rte_memarea_refcnt_update() is undefined if the memarea or pointer does not + * match these requirements. + * + * @note If the memory object's refcnt updated to be lower than zero, an error + * message will be printed, and the memory object will not freed to memrea. + * + * @param ma + * The pointer of memarea. + * @param ptr + * The pointer of memory object which need be updated refcnt. + * @param value + * The value which need be updated. + */ +__rte_experimental +void rte_memarea_refcnt_update(struct rte_memarea *ma, void *ptr, int32_t value); + #ifdef __cplusplus } #endif diff --git a/lib/memarea/version.map b/lib/memarea/version.map index f36a04d7cf..a087d40d5f 100644 --- a/lib/memarea/version.map +++ b/lib/memarea/version.map @@ -1,8 +1,11 @@ EXPERIMENTAL { global: + rte_memarea_alloc; rte_memarea_create; rte_memarea_destroy; + rte_memarea_free; + rte_memarea_refcnt_update; local: *; }; From patchwork Mon Oct 17 03:40:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: fengchengwen X-Patchwork-Id: 118238 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id BB3A8A0556; Mon, 17 Oct 2022 05:47:22 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4485741147; Mon, 17 Oct 2022 05:46:56 +0200 (CEST) Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) by mails.dpdk.org (Postfix) with ESMTP id 633BC4021E for ; Mon, 17 Oct 2022 05:46:49 +0200 (CEST) Received: from dggpeml500024.china.huawei.com (unknown [172.30.72.56]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4MrNG85wW8zHvSG; Mon, 17 Oct 2022 11:46:40 +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; Mon, 17 Oct 2022 11:46:45 +0800 From: Chengwen Feng To: , , , , , CC: , Subject: [PATCH v10 4/7] test/memarea: support alloc/free/refcnt-update test Date: Mon, 17 Oct 2022 03:40:55 +0000 Message-ID: <20221017034058.34176-5-fengchengwen@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221017034058.34176-1-fengchengwen@huawei.com> References: <20220721044648.6817-1-fengchengwen@huawei.com> <20221017034058.34176-1-fengchengwen@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.165.24] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) 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 This patch supports rte_memarea_alloc()/rte_memarea_free()/ rte_memarea_refcnt_update() test. Signed-off-by: Chengwen Feng --- app/test/test_memarea.c | 145 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) diff --git a/app/test/test_memarea.c b/app/test/test_memarea.c index cfd50de45f..00f9d07ed4 100644 --- a/app/test/test_memarea.c +++ b/app/test/test_memarea.c @@ -47,6 +47,12 @@ test_memarea_init_param(struct rte_memarea_param *init) init->mt_safe = 1; } +static void +test_memarea_fill_region(void *ptr, size_t size) +{ + memset(ptr, 0xff, size); +} + static int test_memarea_create_bad_param(void) { @@ -95,8 +101,8 @@ test_memarea_create_bad_param(void) static int test_memarea_create_destroy(void) { + struct rte_memarea *ma, *src_ma; struct rte_memarea_param init; - struct rte_memarea *ma; /* test for create with HEAP */ test_memarea_init_param(&init); @@ -113,6 +119,140 @@ test_memarea_create_destroy(void) RTE_TEST_ASSERT(ma != NULL, "Expected Non-NULL"); rte_memarea_destroy(ma); + /* test for create with another memarea */ + test_memarea_init_param(&init); + init.source = RTE_MEMAREA_SOURCE_LIBC; + src_ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(src_ma != NULL, "Expected Non-NULL"); + test_memarea_init_param(&init); + init.source = RTE_MEMAREA_SOURCE_MEMAREA; + init.total_sz = init.total_sz >> 1; + init.src_memarea = src_ma; + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma != NULL, "Expected Non-NULL"); + rte_memarea_destroy(ma); + rte_memarea_destroy(src_ma); + + return 0; +} + +static int +test_memarea_alloc_fail(void) +{ + struct rte_memarea_param init; + struct rte_memarea *ma; + void *ptr[2]; + + test_memarea_init_param(&init); + init.source = RTE_MEMAREA_SOURCE_LIBC; + init.total_sz = MEMAREA_TEST_DEFAULT_SIZE; + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma != NULL, "Expected Non-NULL"); + + /* test alloc fail with big size */ + ptr[0] = rte_memarea_alloc(ma, MEMAREA_TEST_DEFAULT_SIZE, 0); + RTE_TEST_ASSERT(ptr[0] == NULL, "Expected NULL"); + + /* test alloc fail because no memory */ + ptr[0] = rte_memarea_alloc(ma, MEMAREA_TEST_DEFAULT_SIZE - RTE_CACHE_LINE_SIZE, 0); + RTE_TEST_ASSERT(ptr[0] != NULL, "Expected Non-NULL"); + ptr[1] = rte_memarea_alloc(ma, 1, 0); + RTE_TEST_ASSERT(ptr[1] == NULL, "Expected NULL"); + rte_memarea_free(ma, ptr[0]); + + /* test alloc fail when second fail */ + ptr[0] = rte_memarea_alloc(ma, MEMAREA_TEST_DEFAULT_SIZE >> 1, 0); + RTE_TEST_ASSERT(ptr[0] != NULL, "Expected Non-NULL"); + test_memarea_fill_region(ptr[0], MEMAREA_TEST_DEFAULT_SIZE >> 1); + ptr[1] = rte_memarea_alloc(ma, MEMAREA_TEST_DEFAULT_SIZE >> 1, 0); + RTE_TEST_ASSERT(ptr[1] == NULL, "Expected NULL"); + rte_memarea_free(ma, ptr[0]); + ptr[1] = rte_memarea_alloc(ma, MEMAREA_TEST_DEFAULT_SIZE >> 1, 0); + RTE_TEST_ASSERT(ptr[1] != NULL, "Expected Non-NULL"); + test_memarea_fill_region(ptr[1], MEMAREA_TEST_DEFAULT_SIZE >> 1); + rte_memarea_free(ma, ptr[1]); + + rte_memarea_destroy(ma); + + return 0; +} + +static int +test_memarea_free_fail(void) +{ + struct rte_memarea_param init; + struct rte_memarea *ma; + void *ptr; + + /* prepare env */ + test_memarea_init_param(&init); + init.source = RTE_MEMAREA_SOURCE_LIBC; + init.total_sz = MEMAREA_TEST_DEFAULT_SIZE; + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma != NULL, "Expected Non-NULL"); + + /* test free with refcnt fail */ + ptr = rte_memarea_alloc(ma, MEMAREA_TEST_DEFAULT_SIZE >> 1, 0); + RTE_TEST_ASSERT(ptr != NULL, "Expected Non-NULL"); + test_memarea_fill_region(ptr, MEMAREA_TEST_DEFAULT_SIZE >> 1); + rte_memarea_free(ma, ptr); + rte_memarea_free(ma, ptr); + + /* test update refcnt with fail */ + ptr = rte_memarea_alloc(ma, MEMAREA_TEST_DEFAULT_SIZE >> 1, 0); + RTE_TEST_ASSERT(ptr != NULL, "Expected Non-NULL"); + test_memarea_fill_region(ptr, MEMAREA_TEST_DEFAULT_SIZE >> 1); + rte_memarea_refcnt_update(ma, ptr, -2); + ptr = rte_memarea_alloc(ma, MEMAREA_TEST_DEFAULT_SIZE >> 1, 0); + RTE_TEST_ASSERT(ptr == NULL, "Expected NULL"); + + rte_memarea_destroy(ma); + + return 0; +} + +static int +test_memarea_alloc_free(void) +{ +#define ALLOC_MAX_NUM 8 + struct rte_memarea_param init; + struct rte_memarea *ma; + void *ptr[ALLOC_MAX_NUM]; + int i; + + /* prepare env */ + test_memarea_init_param(&init); + init.source = RTE_MEMAREA_SOURCE_LIBC; + init.total_sz = MEMAREA_TEST_DEFAULT_SIZE; + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma != NULL, "Expected Non-NULL"); + memset(ptr, 0, sizeof(ptr)); + + /* test random alloc and free */ + for (i = 0; i < ALLOC_MAX_NUM; i++) + ptr[i] = rte_memarea_alloc(ma, 1, 0); + + /* test merge left */ + rte_memarea_free(ma, ptr[0]); + rte_memarea_free(ma, ptr[1]); + + /* test merge right */ + rte_memarea_free(ma, ptr[7]); + rte_memarea_free(ma, ptr[6]); + + /* test merge left and right */ + rte_memarea_free(ma, ptr[3]); + rte_memarea_free(ma, ptr[2]); + + /* test merge remains */ + rte_memarea_free(ma, ptr[4]); + rte_memarea_free(ma, ptr[5]); + + /* test free NULL */ + rte_memarea_free(ma, NULL); + + rte_memarea_destroy(ma); + return 0; } @@ -123,6 +263,9 @@ test_memarea(void) MEMAREA_TEST_API_RUN(test_memarea_create_bad_param); MEMAREA_TEST_API_RUN(test_memarea_create_destroy); + MEMAREA_TEST_API_RUN(test_memarea_alloc_fail); + MEMAREA_TEST_API_RUN(test_memarea_free_fail); + MEMAREA_TEST_API_RUN(test_memarea_alloc_free); return test_memarea_retcode(); } From patchwork Mon Oct 17 03:40:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: fengchengwen X-Patchwork-Id: 118239 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 57956A0556; Mon, 17 Oct 2022 05:47:28 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 54BC94281E; Mon, 17 Oct 2022 05:46:57 +0200 (CEST) Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) by mails.dpdk.org (Postfix) with ESMTP id 632EA400D7 for ; Mon, 17 Oct 2022 05:46:49 +0200 (CEST) Received: from dggpeml500024.china.huawei.com (unknown [172.30.72.56]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4MrNGB2ZxNzHvWj; Mon, 17 Oct 2022 11:46:42 +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; Mon, 17 Oct 2022 11:46:45 +0800 From: Chengwen Feng To: , , , , , CC: , Subject: [PATCH v10 5/7] memarea: support dump API Date: Mon, 17 Oct 2022 03:40:56 +0000 Message-ID: <20221017034058.34176-6-fengchengwen@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221017034058.34176-1-fengchengwen@huawei.com> References: <20220721044648.6817-1-fengchengwen@huawei.com> <20221017034058.34176-1-fengchengwen@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.165.24] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) 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 This patch supports rte_memarea_dump() API which could be used for debug. Signed-off-by: Chengwen Feng --- doc/guides/prog_guide/memarea_lib.rst | 3 + lib/memarea/rte_memarea.c | 98 +++++++++++++++++++++++++++ lib/memarea/rte_memarea.h | 21 ++++++ lib/memarea/version.map | 1 + 4 files changed, 123 insertions(+) diff --git a/doc/guides/prog_guide/memarea_lib.rst b/doc/guides/prog_guide/memarea_lib.rst index 8fbfd06a5d..c33a548417 100644 --- a/doc/guides/prog_guide/memarea_lib.rst +++ b/doc/guides/prog_guide/memarea_lib.rst @@ -43,6 +43,9 @@ The ``rte_memarea_refcnt_update()`` function is used to update the memory object's reference count, if the count reaches zero, the memory object will be freed to memarea. ++The ``rte_memarea_dump()`` function is used to dump the internal information ++of a memarea. + Reference --------- diff --git a/lib/memarea/rte_memarea.c b/lib/memarea/rte_memarea.c index a0935dafb6..c58f68df53 100644 --- a/lib/memarea/rte_memarea.c +++ b/lib/memarea/rte_memarea.c @@ -2,6 +2,7 @@ * Copyright(c) 2022 HiSilicon Limited */ +#include #include #include #include @@ -313,3 +314,100 @@ rte_memarea_refcnt_update(struct rte_memarea *ma, void *ptr, int32_t value) memarea_free_elem(ma, elem); memarea_unlock(ma); } + +static const char * +memarea_source_name(enum rte_memarea_source source) +{ + if (source == RTE_MEMAREA_SOURCE_HEAP) + return "heap"; + else if (source == RTE_MEMAREA_SOURCE_LIBC) + return "libc"; + else if (source == RTE_MEMAREA_SOURCE_MEMAREA) + return "memarea"; + else + return "unknown"; +} + +static const char * +memarea_alg_name(enum rte_memarea_alg alg) +{ + if (alg == RTE_MEMAREA_ALG_NEXTFIT) + return "nextfit"; + else + return "unknown"; +} + +static uint32_t +memarea_elem_list_num(struct rte_memarea *ma) +{ + struct memarea_elem *elem; + uint32_t num = 0; + + TAILQ_FOREACH(elem, &ma->elem_list, elem_node) { + if (elem->magic != MEMAREA_AVAILABLE_ELEM_MAGIC && + elem->magic != MEMAREA_ALLOCATED_ELEM_MAGIC) + break; + num++; + } + + return num; +} + +static uint32_t +memarea_free_list_num(struct rte_memarea *ma) +{ + struct memarea_elem *elem; + uint32_t num = 0; + + TAILQ_FOREACH(elem, &ma->free_list, free_node) { + if (elem->magic != MEMAREA_AVAILABLE_ELEM_MAGIC) + break; + num++; + } + + return num; +} + +static void +memarea_dump_all(struct rte_memarea *ma, FILE *f) +{ + struct memarea_elem *elem; + + fprintf(f, " regions:\n"); + TAILQ_FOREACH(elem, &ma->elem_list, elem_node) { + if (elem->magic != MEMAREA_AVAILABLE_ELEM_MAGIC && + elem->magic != MEMAREA_ALLOCATED_ELEM_MAGIC) { + fprintf(f, " magic: 0x%x check fail!\n", elem->magic); + break; + } + fprintf(f, " size: 0x%zx cookie: 0x%x refcnt: %d\n", + elem->size, elem->cookie, elem->refcnt); + } +} + +int +rte_memarea_dump(struct rte_memarea *ma, FILE *f, bool dump_all) +{ + if (ma == NULL || f == NULL) + return -EINVAL; + + memarea_lock(ma); + fprintf(f, "memarea name: %s\n", ma->init.name); + fprintf(f, " source: %s\n", memarea_source_name(ma->init.source)); + if (ma->init.source == RTE_MEMAREA_SOURCE_HEAP) + fprintf(f, " heap-numa-socket: %d\n", ma->init.numa_socket); + else if (ma->init.source == RTE_MEMAREA_SOURCE_MEMAREA) + fprintf(f, " source-memarea: %s\n", ma->init.src_memarea->init.name); + fprintf(f, " algorithm: %s\n", memarea_alg_name(ma->init.alg)); + fprintf(f, " total-size: 0x%zx\n", ma->init.total_sz); + fprintf(f, " mt-safe: %s\n", ma->init.mt_safe ? "yes" : "no"); + fprintf(f, " total-regions: %u\n", memarea_elem_list_num(ma)); + fprintf(f, " total-free-regions: %u\n", memarea_free_list_num(ma)); + fprintf(f, " alloc_fails: %" PRIu64 "\n", ma->alloc_fails); + fprintf(f, " refcnt_check_fails: %" PRIu64 "\n", ma->refcnt_check_fails); + if (dump_all) + memarea_dump_all(ma, f); + memarea_unlock(ma); + + return 0; +} diff --git a/lib/memarea/rte_memarea.h b/lib/memarea/rte_memarea.h index 31c499ec07..61042a8d0d 100644 --- a/lib/memarea/rte_memarea.h +++ b/lib/memarea/rte_memarea.h @@ -191,6 +191,27 @@ void rte_memarea_free(struct rte_memarea *ma, void *ptr); __rte_experimental void rte_memarea_refcnt_update(struct rte_memarea *ma, void *ptr, int32_t value); +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Dump memarea. + * + * Dump one memarea. + * + * @param ma + * The pointer of memarea. + * @param f + * The file to write the output to. + * @param dump_all + * Indicate whether to dump the allocated and free memory objects information. + * + * @return + * 0 on success. Otherwise negative value is returned. + */ +__rte_experimental +int rte_memarea_dump(struct rte_memarea *ma, FILE *f, bool dump_all); + #ifdef __cplusplus } #endif diff --git a/lib/memarea/version.map b/lib/memarea/version.map index a087d40d5f..6d75f9f7c4 100644 --- a/lib/memarea/version.map +++ b/lib/memarea/version.map @@ -4,6 +4,7 @@ EXPERIMENTAL { rte_memarea_alloc; rte_memarea_create; rte_memarea_destroy; + rte_memarea_dump; rte_memarea_free; rte_memarea_refcnt_update; From patchwork Mon Oct 17 03:40:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: fengchengwen X-Patchwork-Id: 118237 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id EECB3A0556; Mon, 17 Oct 2022 05:47:17 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 600D7427F4; Mon, 17 Oct 2022 05:46:55 +0200 (CEST) Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) by mails.dpdk.org (Postfix) with ESMTP id 632EF40143 for ; Mon, 17 Oct 2022 05:46:49 +0200 (CEST) Received: from dggpeml500024.china.huawei.com (unknown [172.30.72.56]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4MrNGB2wXxzHvdn; Mon, 17 Oct 2022 11:46:42 +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; Mon, 17 Oct 2022 11:46:46 +0800 From: Chengwen Feng To: , , , , , CC: , Subject: [PATCH v10 6/7] test/memarea: support dump test Date: Mon, 17 Oct 2022 03:40:57 +0000 Message-ID: <20221017034058.34176-7-fengchengwen@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221017034058.34176-1-fengchengwen@huawei.com> References: <20220721044648.6817-1-fengchengwen@huawei.com> <20221017034058.34176-1-fengchengwen@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.165.24] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) 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 This patch supports rte_memarea_dump() test. Signed-off-by: Chengwen Feng --- app/test/test_memarea.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/app/test/test_memarea.c b/app/test/test_memarea.c index 00f9d07ed4..da712a14e8 100644 --- a/app/test/test_memarea.c +++ b/app/test/test_memarea.c @@ -256,6 +256,40 @@ test_memarea_alloc_free(void) return 0; } +static int +test_memarea_dump(void) +{ + struct rte_memarea_param init; + struct rte_memarea *ma; + int ret; + + /* prepare env */ + test_memarea_init_param(&init); + init.source = RTE_MEMAREA_SOURCE_LIBC; + init.total_sz = MEMAREA_TEST_DEFAULT_SIZE; + ma = rte_memarea_create(&init); + RTE_TEST_ASSERT(ma != NULL, "Expected Non-NULL"); + + /* test for invalid parameters */ + ret = rte_memarea_dump(NULL, stderr, false); + RTE_TEST_ASSERT(ret == -EINVAL, "Expected EINVAL"); + ret = rte_memarea_dump(ma, NULL, false); + RTE_TEST_ASSERT(ret == -EINVAL, "Expected EINVAL"); + + /* test for dump */ + (void)rte_memarea_alloc(ma, 1, 0); + (void)rte_memarea_alloc(ma, 1, 0); + (void)rte_memarea_alloc(ma, 1, 0); + (void)rte_memarea_alloc(ma, MEMAREA_TEST_DEFAULT_SIZE, 0); + (void)rte_memarea_alloc(ma, MEMAREA_TEST_DEFAULT_SIZE, 0); + ret = rte_memarea_dump(ma, stderr, true); + RTE_TEST_ASSERT(ret == 0, "Expected ZERO"); + + rte_memarea_destroy(ma); + + return 0; +} + static int test_memarea(void) { @@ -266,6 +300,7 @@ test_memarea(void) MEMAREA_TEST_API_RUN(test_memarea_alloc_fail); MEMAREA_TEST_API_RUN(test_memarea_free_fail); MEMAREA_TEST_API_RUN(test_memarea_alloc_free); + MEMAREA_TEST_API_RUN(test_memarea_dump); return test_memarea_retcode(); } From patchwork Mon Oct 17 03:40:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: fengchengwen X-Patchwork-Id: 118240 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 14F62A0556; Mon, 17 Oct 2022 05:47:34 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 435204282E; Mon, 17 Oct 2022 05:46:58 +0200 (CEST) Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) by mails.dpdk.org (Postfix) with ESMTP id 1633640143 for ; Mon, 17 Oct 2022 05:46:50 +0200 (CEST) Received: from dggpeml500024.china.huawei.com (unknown [172.30.72.56]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4MrNGB4dqqzHvh1; Mon, 17 Oct 2022 11:46:42 +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; Mon, 17 Oct 2022 11:46:46 +0800 From: Chengwen Feng To: , , , , , CC: , Subject: [PATCH v10 7/7] app/test: add memarea to malloc-perf-autotest Date: Mon, 17 Oct 2022 03:40:58 +0000 Message-ID: <20221017034058.34176-8-fengchengwen@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221017034058.34176-1-fengchengwen@huawei.com> References: <20220721044648.6817-1-fengchengwen@huawei.com> <20221017034058.34176-1-fengchengwen@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.165.24] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) 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 This patch adds memarea perftest to malloc_perf_autotest. The memarea perftest contains two part: 1) rte_memarea.heap: the memory source comes from invoking rte_malloc_socket(). 2) rte_memarea.libc: the memory source comes from invoking malloc(). Test platform: Kunpeng920 Test command: dpdk-test -a 0000:7d:00.3 -l 10-12 Test result: USER1: Performance: rte_memarea.heap USER1: Size (B) Runs Alloc (us) Free (us) Total (us) memset (us) USER1: 64 10000 0.04 0.04 0.08 0.01 USER1: 128 10000 0.03 0.03 0.06 0.01 USER1: 1024 10000 0.03 0.04 0.07 0.20 USER1: 4096 10000 0.03 0.05 0.08 0.34 USER1: 65536 10000 0.10 0.06 0.16 2.15 USER1: 1048576 1023 0.11 0.04 0.15 29.15 USER1: 2097152 511 0.12 0.04 0.16 57.72 USER1: 4194304 255 0.14 0.04 0.17 114.93 USER1: 16777216 63 0.15 0.07 0.21 457.51 USER1: 1073741824 Interrupted: out of memory. USER1: Performance: rte_memarea.libc USER1: Size (B) Runs Alloc (us) Free (us) Total (us) memset (us) USER1: 64 10000 0.12 0.03 0.15 0.01 USER1: 128 10000 0.03 0.03 0.06 0.01 USER1: 1024 10000 0.15 0.04 0.19 0.19 USER1: 4096 10000 0.51 0.04 0.54 0.34 USER1: 65536 10000 9.40 0.06 9.46 2.14 USER1: 1048576 1023 48.39 0.07 48.46 29.15 USER1: 2097152 511 0.11 0.06 0.17 57.79 USER1: 4194304 255 0.11 0.06 0.18 114.82 USER1: 16777216 63 0.12 0.07 0.19 457.86 USER1: 1073741824 Interrupted: out of memory. Compared with rte_malloc: USER1: Performance: rte_malloc USER1: Size (B) Runs Alloc (us) Free (us) Total (us) memset (us) USER1: 64 10000 0.14 0.07 0.21 0.01 USER1: 128 10000 0.10 0.05 0.15 0.01 USER1: 1024 10000 0.11 0.18 0.29 0.21 USER1: 4096 10000 0.13 0.39 0.53 0.35 USER1: 65536 10000 0.17 2.27 2.44 2.15 USER1: 1048576 10000 37.21 71.63 108.84 29.08 USER1: 2097152 10000 8831.15 160.02 8991.17 63.52 USER1: 4194304 10000 47131.88 413.75 47545.62 173.79 USER1: 16777216 4221 119604.60 2209.73 121814.34 964.42 USER1: 1073741824 31 335058.32 223369.31 558427.63 62440.87 Note: The rte_malloc time includes obtaining memory from the system, but rte_memarea time don't includes these (it uses pre-allocated policy). Signed-off-by: Chengwen Feng --- app/test/test_malloc_perf.c | 82 +++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/app/test/test_malloc_perf.c b/app/test/test_malloc_perf.c index ccec43ae84..0972f4dec7 100644 --- a/app/test/test_malloc_perf.c +++ b/app/test/test_malloc_perf.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "test.h" @@ -20,6 +21,8 @@ typedef void * (memset_t)(void *addr, int value, size_t size); static const uint64_t KB = 1 << 10; static const uint64_t GB = 1 << 30; +static struct rte_memarea *ma_perftest_handle; + static double tsc_to_us(uint64_t tsc, size_t runs) { @@ -147,6 +150,80 @@ memzone_free(void *addr) rte_memzone_free((struct rte_memzone *)addr); } +static const char * +memarea_perftest_source_name(enum rte_memarea_source source) +{ + if (source == RTE_MEMAREA_SOURCE_HEAP) + return "heap"; + else if (source == RTE_MEMAREA_SOURCE_LIBC) + return "libc"; + else + return "unknown"; +} + +static int +memarea_perftest_pre_env(enum rte_memarea_source source) +{ + struct rte_memarea_param init; + + memset(&init, 0, sizeof(init)); + snprintf(init.name, sizeof(init.name), "perftest"); + init.source = source; + init.alg = RTE_MEMAREA_ALG_NEXTFIT; + init.total_sz = GB; + init.mt_safe = 1; + init.numa_socket = SOCKET_ID_ANY; + + ma_perftest_handle = rte_memarea_create(&init); + if (ma_perftest_handle == NULL) { + fprintf(stderr, "memarea create failed, skip memarea source: %s perftest!\n", + memarea_perftest_source_name(source)); + return -1; + } + return 0; +} + +static void +memarea_perftest_clear_env(void) +{ + rte_memarea_destroy(ma_perftest_handle); + ma_perftest_handle = NULL; +} + +static void * +memarea_perftest_alloc(const char *name, size_t size, unsigned int align) +{ + RTE_SET_USED(name); + RTE_SET_USED(align); + return rte_memarea_alloc(ma_perftest_handle, size, 0); +} + +static void +memarea_perftest_free(void *addr) +{ + rte_memarea_free(ma_perftest_handle, addr); +} + +static int +memarea_perftest(enum rte_memarea_source source, double memset_gb_us, size_t max_runs) +{ + char test_name[64] = { 0 }; + + if (memarea_perftest_pre_env(source) < 0) + return 0; + + snprintf(test_name, sizeof(test_name), "rte_memarea.%s", + memarea_perftest_source_name(source)); + if (test_alloc_perf(test_name, memarea_perftest_alloc, memarea_perftest_free, + memset, memset_gb_us, max_runs) < 0) { + memarea_perftest_clear_env(); + return -1; + } + + memarea_perftest_clear_env(); + return 0; +} + static int test_malloc_perf(void) { @@ -168,6 +245,11 @@ test_malloc_perf(void) NULL, memset_us_gb, RTE_MAX_MEMZONE - 1) < 0) return -1; + if (memarea_perftest(RTE_MEMAREA_SOURCE_HEAP, memset_us_gb, MAX_RUNS) < 0) + return -1; + if (memarea_perftest(RTE_MEMAREA_SOURCE_LIBC, memset_us_gb, MAX_RUNS) < 0) + return -1; + return 0; }