From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id DB01B41C49;
	Thu,  9 Feb 2023 07:42:23 +0100 (CET)
Received: from mails.dpdk.org (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id 9A09E41611;
	Thu,  9 Feb 2023 07:42:21 +0100 (CET)
Received: from szxga08-in.huawei.com (szxga08-in.huawei.com [45.249.212.255])
 by mails.dpdk.org (Postfix) with ESMTP id D7EB240EDC
 for <dev@dpdk.org>; Thu,  9 Feb 2023 07:42:17 +0100 (CET)
Received: from dggpeml500024.china.huawei.com (unknown [172.30.72.57])
 by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4PC6g66MMVz16NXB;
 Thu,  9 Feb 2023 14:40:02 +0800 (CST)
Received: from localhost.localdomain (10.50.163.32) 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.34; Thu, 9 Feb 2023 14:42:15 +0800
From: Chengwen Feng <fengchengwen@huawei.com>
To: <thomas@monjalon.net>, <david.marchand@redhat.com>
CC: <dev@dpdk.org>, <mb@smartsharesystems.com>, <anatoly.burakov@intel.com>,
 <dmitry.kozliuk@gmail.com>, <jerinjacobk@gmail.com>, <hofors@lysator.liu.se>, 
 <stephen@networkplumber.org>
Subject: [PATCH v14 5/6] memarea: support dump API
Date: Thu, 9 Feb 2023 06:36:09 +0000
Message-ID: <20230209063610.35501-6-fengchengwen@huawei.com>
X-Mailer: git-send-email 2.17.1
In-Reply-To: <20230209063610.35501-1-fengchengwen@huawei.com>
References: <20220721044648.6817-1-fengchengwen@huawei.com>
 <20230209063610.35501-1-fengchengwen@huawei.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 8bit
X-Originating-IP: [10.50.163.32]
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 <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=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 <fengchengwen@huawei.com>
Reviewed-by: Dongdong Liu <liudongdong3@huawei.com>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
---
 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 55ca4b1166..d9fac69ed3 100644
--- a/doc/guides/prog_guide/memarea_lib.rst
+++ b/doc/guides/prog_guide/memarea_lib.rst
@@ -37,6 +37,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 0b53bfe757..55fae30bc3 100644
--- a/lib/memarea/rte_memarea.c
+++ b/lib/memarea/rte_memarea.c
@@ -348,3 +348,101 @@ 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, 2);
+		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, 2);
+		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)
+		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_ma->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 02b4825461..c871accda6 100644
--- a/lib/memarea/rte_memarea.h
+++ b/lib/memarea/rte_memarea.h
@@ -157,6 +157,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.
+ */
+__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: *;
-- 
2.17.1