This patch supports rte_memarea_dump() API which could be used for debug. Signed-off-by: Chengwen Feng <fengcheng...@huawei.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 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 <inttypes.h> #include <stdio.h> #include <stdlib.h> #include <sys/queue.h> @@ -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; -- 2.17.1