[v14,5/6] memarea: support dump API

Message ID 20230209063610.35501-6-fengchengwen@huawei.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series introduce memarea library |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

fengchengwen Feb. 9, 2023, 6:36 a.m. UTC
  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(+)
  

Comments

Burakov, Anatoly June 22, 2023, 3:55 p.m. UTC | #1
On 2/9/2023 6:36 AM, Chengwen Feng wrote:
> 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>
> ---

Provisionally,

Acked-by: Anatoly Burakov <anatoly.burakov@intel.com>

As long as below is addressed.

> +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;

I feel like the API is inconsistent in this way. I would suggest picking 
a method of error reporting, and sticking with it. I would suggest 
returning 0/-1 or ptr/NULL with rte_errno set to indicate error, as that 
is how most libraries in DPDK behave.
  
fengchengwen June 28, 2023, 1:25 a.m. UTC | #2
Hi Anatoly,

  Thanks for your review, a lot of valuable advice.

  PS: This library stays for a long time, want to hear TB's opinion: whether to continue or stop.
      If continue I will push a new version.

Thanks.

On 2023/6/22 23:55, Burakov, Anatoly wrote:
> On 2/9/2023 6:36 AM, Chengwen Feng wrote:
>> 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>
>> ---
> 
> Provisionally,
> 
> Acked-by: Anatoly Burakov <anatoly.burakov@intel.com>
> 
> As long as below is addressed.
> 
>> +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;
> 
> I feel like the API is inconsistent in this way. I would suggest picking a method of error reporting, and sticking with it. I would suggest returning 0/-1 or ptr/NULL with rte_errno set to indicate error, as that is how most libraries in DPDK behave.
>
  
Thomas Monjalon June 28, 2023, 1:39 a.m. UTC | #3
28/06/2023 03:25, fengchengwen:
> Hi Anatoly,
> 
>   Thanks for your review, a lot of valuable advice.
> 
>   PS: This library stays for a long time, want to hear TB's opinion: whether to continue or stop.
>       If continue I will push a new version.

Would you be able to attend the techboard meeting today (3pm UTC)?
	https://core.dpdk.org/techboard/minutes/
We could discuss the value of this library.
Anatoly, would you be able to prepare some arguments as well?
  
fengchengwen June 28, 2023, 1:48 a.m. UTC | #4
On 2023/6/28 9:39, Thomas Monjalon wrote:
> 28/06/2023 03:25, fengchengwen:
>> Hi Anatoly,
>>
>>   Thanks for your review, a lot of valuable advice.
>>
>>   PS: This library stays for a long time, want to hear TB's opinion: whether to continue or stop.
>>       If continue I will push a new version.
> 
> Would you be able to attend the techboard meeting today (3pm UTC)?

Great, I will attend, Thanks.

> 	https://core.dpdk.org/techboard/minutes/
> We could discuss the value of this library.
> Anatoly, would you be able to prepare some arguments as well?
> 
> 
> .
>
  
Burakov, Anatoly July 3, 2023, 10:29 a.m. UTC | #5
On 6/28/2023 2:39 AM, Thomas Monjalon wrote:
> 28/06/2023 03:25, fengchengwen:
>> Hi Anatoly,
>>
>>    Thanks for your review, a lot of valuable advice.
>>
>>    PS: This library stays for a long time, want to hear TB's opinion: whether to continue or stop.
>>        If continue I will push a new version.
> 
> Would you be able to attend the techboard meeting today (3pm UTC)?
> 	https://core.dpdk.org/techboard/minutes/
> We could discuss the value of this library.
> Anatoly, would you be able to prepare some arguments as well?
> 
> 

Apologies, I missed this email :( I don't see any minutes, there was no 
techboard?

As for "arguments", I have no strong opinions on whether this library 
should be added or not. It seems like a viable alternative to using 
mempools when a certain amount of scratch space is needed for whatever 
reasons (I remember having discussions about current allocator being too 
heavyweight for this kind of scenario), so to me, it's not that I'm 
particularly fond of the library, it's moreso that I think that it 
sounds useful and I don't have any strong objections to its inclusion.
  

Patch

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: *;