From patchwork Thu Jul 20 09:22:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: fengchengwen X-Patchwork-Id: 129655 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 3B43442EBF; Thu, 20 Jul 2023 11:31:11 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 00D6E40EE3; Thu, 20 Jul 2023 11:31:11 +0200 (CEST) Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) by mails.dpdk.org (Postfix) with ESMTP id E31AC40DF5 for ; Thu, 20 Jul 2023 11:31:09 +0200 (CEST) Received: from dggpeml100024.china.huawei.com (unknown [172.30.72.56]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4R66mN40MtzNmVD; Thu, 20 Jul 2023 17:27:48 +0800 (CST) Received: from localhost.localdomain (10.50.163.32) by dggpeml100024.china.huawei.com (7.185.36.115) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Thu, 20 Jul 2023 17:31:08 +0800 From: Chengwen Feng To: , CC: , , , , , , Subject: [PATCH v19 5/6] memarea: support dump API Date: Thu, 20 Jul 2023 09:22:53 +0000 Message-ID: <20230720092254.54157-6-fengchengwen@huawei.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230720092254.54157-1-fengchengwen@huawei.com> References: <20220721044648.6817-1-fengchengwen@huawei.com> <20230720092254.54157-1-fengchengwen@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.50.163.32] X-ClientProxiedBy: dggems705-chm.china.huawei.com (10.3.19.182) To dggpeml100024.china.huawei.com (7.185.36.115) 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 Reviewed-by: Dongdong Liu Acked-by: Morten Brørup Acked-by: Anatoly Burakov --- doc/guides/prog_guide/memarea_lib.rst | 3 + lib/memarea/rte_memarea.c | 100 ++++++++++++++++++++++++++ lib/memarea/rte_memarea.h | 21 ++++++ lib/memarea/version.map | 1 + 4 files changed, 125 insertions(+) diff --git a/doc/guides/prog_guide/memarea_lib.rst b/doc/guides/prog_guide/memarea_lib.rst index 157baf3c7e..ef22294664 100644 --- a/doc/guides/prog_guide/memarea_lib.rst +++ b/doc/guides/prog_guide/memarea_lib.rst @@ -39,6 +39,9 @@ the memarea. The ``rte_memarea_free()`` function is used to free one memory object which allocated by ``rte_memarea_alloc()``. ++The ``rte_memarea_dump()`` function is used to dump the internal information ++of a memarea. + Debug Mode ---------- diff --git a/lib/memarea/rte_memarea.c b/lib/memarea/rte_memarea.c index 7a35c875a7..d5d9a46736 100644 --- a/lib/memarea/rte_memarea.c +++ b/lib/memarea/rte_memarea.c @@ -361,3 +361,103 @@ rte_memarea_free(struct rte_memarea *ma, void *ptr) 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_algorithm alg) +{ + if (alg == RTE_MEMAREA_ALGORITHM_NEXTFIT) + return "nextfit"; + else + return "unknown"; +} + +static void +memarea_dump_objects_brief(struct rte_memarea *ma, FILE *f) +{ + uint32_t total_objs = 0, total_avail_objs = 0; + struct memarea_objhdr *hdr; + size_t total_avail_sz = 0; + + TAILQ_FOREACH(hdr, &ma->obj_list, obj_next) { + if (hdr == ma->guard_hdr) + break; + memarea_check_cookie(ma, hdr, COOKIE_EXPECT_STATUS_VALID); + total_objs++; + if (!MEMAREA_OBJECT_IS_ALLOCATED(hdr)) { + total_avail_objs++; + total_avail_sz += MEMAREA_OBJECT_GET_SIZE(hdr); + } + } + fprintf(f, " total-objects: %u\n", total_objs); + fprintf(f, " total-avail-objects: %u\n", total_avail_objs); + fprintf(f, " total-avail-objects-size: 0x%zx\n", total_avail_sz); +} + +static void +memarea_dump_objects_detail(struct rte_memarea *ma, FILE *f) +{ + struct memarea_objhdr *hdr; + size_t offset; + void *ptr; + + fprintf(f, " objects:\n"); + TAILQ_FOREACH(hdr, &ma->obj_list, obj_next) { + if (hdr == ma->guard_hdr) + break; + memarea_check_cookie(ma, hdr, COOKIE_EXPECT_STATUS_VALID); + ptr = RTE_PTR_ADD(hdr, sizeof(struct memarea_objhdr)); + offset = RTE_PTR_DIFF(ptr, ma->area_base); +#ifdef RTE_LIBRTE_MEMAREA_DEBUG + fprintf(f, " %p off: 0x%zx size: 0x%zx %s\n", + ptr, offset, MEMAREA_OBJECT_GET_SIZE(hdr), + MEMAREA_OBJECT_IS_ALLOCATED(hdr) ? "allocated" : ""); +#else + fprintf(f, " off: 0x%zx size: 0x%zx %s\n", + offset, MEMAREA_OBJECT_GET_SIZE(hdr), + MEMAREA_OBJECT_IS_ALLOCATED(hdr) ? "allocated" : ""); +#endif + } +} + +int +rte_memarea_dump(struct rte_memarea *ma, FILE *f, bool dump_all) +{ + if (ma == NULL || f == NULL) { + rte_errno = EINVAL; + return -1; + } + + 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.heap.socket_id); + else if (ma->init.source == RTE_MEMAREA_SOURCE_MEMAREA) + fprintf(f, " source-memarea: %s\n", ma->init.ma.src->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"); +#ifdef RTE_LIBRTE_MEMAREA_DEBUG + fprintf(f, " area-base: %p\n", ma->area_base); + fprintf(f, " guard-header: %p\n", ma->guard_hdr); +#endif + memarea_dump_objects_brief(ma, f); + if (dump_all) + memarea_dump_objects_detail(ma, f); + memarea_unlock(ma); + + return 0; +} diff --git a/lib/memarea/rte_memarea.h b/lib/memarea/rte_memarea.h index bb1bd5bae5..fa57f6c455 100644 --- a/lib/memarea/rte_memarea.h +++ b/lib/memarea/rte_memarea.h @@ -180,6 +180,27 @@ void *rte_memarea_alloc(struct rte_memarea *ma, size_t size); __rte_experimental void rte_memarea_free(struct rte_memarea *ma, void *ptr); +/** + * @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 (the rte_errno is set). + */ +__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 effbd0b488..9513d91e0b 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; local: *;