malloc: add function to dump heap contents

Malloc heap is now a doubly linked list, so it's now possible to
iterate over each malloc element regardless of its state.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
Tested-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
Tested-by: Hemant Agrawal <hemant.agrawal@nxp.com>
Tested-by: Gowrishankar Muthukrishnan <gowrishankar.m@linux.vnet.ibm.com>
This commit is contained in:
Anatoly Burakov 2018-04-11 13:29:39 +01:00 committed by Thomas Monjalon
parent bb372060da
commit 30bc6bf0d5
7 changed files with 83 additions and 0 deletions

View File

@ -13,6 +13,7 @@
#include <stdio.h>
#include <stddef.h>
#include <rte_compat.h>
#include <rte_memory.h>
#ifdef __cplusplus
@ -277,6 +278,15 @@ rte_malloc_get_socket_stats(int socket,
void
rte_malloc_dump_stats(FILE *f, const char *type);
/**
* Dump contents of all malloc heaps to a file.
*
* @param f
* A pointer to a file for output
*/
void __rte_experimental
rte_malloc_dump_heaps(FILE *f);
/**
* Set the maximum amount of allocated memory for this type.
*

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2014 Intel Corporation
*/
#include <inttypes.h>
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
@ -434,3 +435,26 @@ malloc_elem_resize(struct malloc_elem *elem, size_t size)
}
return 0;
}
static inline const char *
elem_state_to_str(enum elem_state state)
{
switch (state) {
case ELEM_PAD:
return "PAD";
case ELEM_BUSY:
return "BUSY";
case ELEM_FREE:
return "FREE";
}
return "ERROR";
}
void
malloc_elem_dump(const struct malloc_elem *elem, FILE *f)
{
fprintf(f, "Malloc element at %p (%s)\n", elem,
elem_state_to_str(elem->state));
fprintf(f, " len: 0x%zx pad: 0x%" PRIx32 "\n", elem->size, elem->pad);
fprintf(f, " prev: %p next: %p\n", elem->prev, elem->next);
}

View File

@ -148,6 +148,12 @@ malloc_elem_free(struct malloc_elem *elem);
int
malloc_elem_resize(struct malloc_elem *elem, size_t size);
/*
* dump contents of malloc elem to a file.
*/
void
malloc_elem_dump(const struct malloc_elem *elem, FILE *f);
/*
* Given an element size, compute its freelist index.
*/

View File

@ -217,6 +217,28 @@ malloc_heap_get_stats(struct malloc_heap *heap,
return 0;
}
/*
* Function to retrieve data for heap on given socket
*/
void
malloc_heap_dump(struct malloc_heap *heap, FILE *f)
{
struct malloc_elem *elem;
rte_spinlock_lock(&heap->lock);
fprintf(f, "Heap size: 0x%zx\n", heap->total_size);
fprintf(f, "Heap alloc count: %u\n", heap->alloc_count);
elem = heap->first;
while (elem) {
malloc_elem_dump(elem, f);
elem = elem->next;
}
rte_spinlock_unlock(&heap->lock);
}
int
rte_eal_malloc_heap_init(void)
{

View File

@ -37,6 +37,9 @@ int
malloc_heap_get_stats(struct malloc_heap *heap,
struct rte_malloc_socket_stats *socket_stats);
void
malloc_heap_dump(struct malloc_heap *heap, FILE *f);
int
rte_eal_malloc_heap_init(void);

View File

@ -181,6 +181,23 @@ rte_malloc_get_socket_stats(int socket,
return malloc_heap_get_stats(&mcfg->malloc_heaps[socket], socket_stats);
}
/*
* Function to dump contents of all heaps
*/
void __rte_experimental
rte_malloc_dump_heaps(FILE *f)
{
struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
unsigned int idx;
for (idx = 0; idx < rte_socket_count(); idx++) {
unsigned int socket = rte_socket_id_by_idx(idx);
fprintf(f, "Heap on socket %i:\n", socket);
malloc_heap_dump(&mcfg->malloc_heaps[socket], f);
}
}
/*
* Print stats on memory type. If type is NULL, info on all types is printed
*/

View File

@ -222,6 +222,7 @@ EXPERIMENTAL {
rte_eal_hotplug_remove;
rte_eal_mbuf_user_pool_ops;
rte_log_register_type_and_pick_level;
rte_malloc_dump_heaps;
rte_mp_action_register;
rte_mp_action_unregister;
rte_mp_reply;