memdump: add biggest allocated node dump

Signed-off-by: buxiasen <buxiasen@xiaomi.com>
This commit is contained in:
buxiasen 2024-07-25 23:48:53 +08:00 committed by GUIDINGLI
parent fd6634ecb5
commit fd9a9f67cc
5 changed files with 206 additions and 0 deletions

View file

@ -434,6 +434,9 @@ static ssize_t memdump_read(FAR struct file *filep, FAR char *buffer,
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD > 0
"/mempool"
#endif
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
"/biggest"
#endif
#if CONFIG_MM_BACKTRACE > 0
"/on/off"
#endif
@ -446,6 +449,9 @@ static ssize_t memdump_read(FAR struct file *filep, FAR char *buffer,
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD > 0
"mempool: dump all mempool alloc node\n"
#endif
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
"biggest: dump allocated top n node\n"
#endif
#if CONFIG_MM_BACKTRACE > 0
"on/off: set backtrace enabled state\n"
#endif
@ -573,6 +579,27 @@ static ssize_t memdump_write(FAR struct file *filep, FAR const char *buffer,
break;
#endif
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD > 0
case 'm':
dump.pid = PID_MM_MEMPOOL;
# if CONFIG_MM_BACKTRACE >= 0
p = (FAR char *)buffer + 7;
goto dump;
# endif
break;
#endif
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
case 'b':
dump.pid = PID_MM_BIGGEST;
# if CONFIG_MM_BACKTRACE >= 0
p = (FAR char *)buffer + 7;
goto dump;
# endif
break;
#endif
#if CONFIG_MM_BACKTRACE >= 0
default:
if (!isdigit(buffer[0]))

View file

@ -35,6 +35,7 @@
/* Special PID to query the info about alloc, free and mempool */
#define PID_MM_BIGGEST ((pid_t)-5)
#define PID_MM_FREE ((pid_t)-4)
#define PID_MM_ALLOC ((pid_t)-3)
#define PID_MM_LEAK ((pid_t)-2)

View file

@ -463,4 +463,12 @@ config MM_FREE_DELAYCOUNT_MAX
the value decides the maximum number of memory nodes that
will be delayed to free.
config MM_HEAP_BIGGEST_COUNT
int "The largest malloc element dump count"
default 30
---help---
The dump support for largest allocated memory.
If too big, should take care of stack usage.
Define 0 to disable largest allocated element dump feature.
source "mm/iob/Kconfig"

View file

@ -43,10 +43,19 @@
* Private Types
****************************************************************************/
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
struct mm_memdump_priv_s
{
FAR const struct mm_memdump_s *dump;
FAR struct mm_allocnode_s *node[CONFIG_MM_HEAP_BIGGEST_COUNT];
size_t filled;
};
#else
struct mm_memdump_priv_s
{
FAR const struct mm_memdump_s *dump;
};
#endif
/****************************************************************************
* Private Functions
@ -77,6 +86,52 @@ static void memdump_allocnode(FAR struct mm_allocnode_s *node)
#endif
}
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
static int memdump_record_comare(FAR const void *a, FAR const void *b)
{
FAR struct mm_allocnode_s *node_a = *(FAR struct mm_allocnode_s **)a;
FAR struct mm_allocnode_s *node_b = *(FAR struct mm_allocnode_s **)b;
size_t size_a = MM_SIZEOF_NODE(node_a);
size_t size_b = MM_SIZEOF_NODE(node_b);
return size_a > size_b ? 1 : -1;
}
static void memdump_record_biggest(FAR struct mm_memdump_priv_s *priv,
FAR struct mm_allocnode_s *node)
{
if (priv->filled < CONFIG_MM_HEAP_BIGGEST_COUNT)
{
priv->node[priv->filled] = node;
priv->filled++;
}
else
{
if (MM_SIZEOF_NODE(node) <= MM_SIZEOF_NODE(priv->node[0]))
{
return;
}
priv->node[0] = node;
}
if (priv->filled > 1)
{
qsort(priv->node, priv->filled, sizeof(struct mm_allocnode_s *),
memdump_record_comare);
}
}
static void memdump_dump_biggestnodes(FAR struct mm_memdump_priv_s *priv)
{
size_t i;
for (i = 0; i < priv->filled; i++)
{
memdump_allocnode(priv->node[i]);
}
}
#endif
static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
{
FAR struct mm_memdump_priv_s *priv = arg;
@ -91,6 +146,12 @@ static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
{
memdump_allocnode(node);
}
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
else if (dump->pid == PID_MM_BIGGEST && MM_DUMP_SEQNO(dump, node))
{
memdump_record_biggest(priv, node);
}
#endif
}
else if (dump->pid == PID_MM_FREE)
{
@ -156,6 +217,20 @@ void mm_memdump(FAR struct mm_heap_s *heap,
syslog(LOG_INFO, "%12s%*s\n", "Size", BACKTRACE_PTR_FMT_WIDTH,
"Address");
}
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
else if (dump->pid == PID_MM_BIGGEST)
{
syslog(LOG_INFO, "Memdump biggest allocated top %d\n",
CONFIG_MM_HEAP_BIGGEST_COUNT);
# if CONFIG_MM_BACKTRACE < 0
syslog(LOG_INFO, "%12s%*s\n", "Size", BACKTRACE_PTR_FMT_WIDTH,
"Address");
# else
syslog(LOG_INFO, "%6s%12s%12s%*s %s\n", "PID", "Size", "Sequence",
BACKTRACE_PTR_FMT_WIDTH, "Address", "Backtrace");
# endif
}
#endif
#ifdef CONFIG_MM_HEAP_MEMPOOL
mempool_multiple_memdump(heap->mm_mpool, dump);
@ -170,4 +245,10 @@ void mm_memdump(FAR struct mm_heap_s *heap,
syslog(LOG_INFO, "%12s%12s\n", "Total Blks", "Total Size");
syslog(LOG_INFO, "%12d%12d\n", info.aordblks, info.uordblks);
}
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
else if (dump->pid == PID_MM_BIGGEST)
{
memdump_dump_biggestnodes(&priv);
}
#endif
}

View file

@ -131,10 +131,25 @@ struct mm_mallinfo_handler_s
FAR struct mallinfo_task *info;
};
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
struct mm_tlsf_node_s
{
FAR void *ptr;
size_t size;
};
struct mm_memdump_priv_s
{
FAR const struct mm_memdump_s *dump;
struct mm_tlsf_node_s node[CONFIG_MM_HEAP_BIGGEST_COUNT];
size_t filled;
};
#else
struct mm_memdump_priv_s
{
FAR const struct mm_memdump_s *dump;
};
#endif
/****************************************************************************
* Private Function Prototypes
@ -168,6 +183,54 @@ static void memdump_allocnode(FAR void *ptr, size_t size)
#endif
}
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
static int memdump_record_comare(FAR const void *a, FAR const void *b)
{
FAR struct mm_tlsf_node_s *node_a = (FAR struct mm_tlsf_node_s *)a;
FAR struct mm_tlsf_node_s *node_b = (FAR struct mm_tlsf_node_s *)b;
size_t size_a = node_a->size;
size_t size_b = node_b->size;
return size_a > size_b ? 1 : -1;
}
static void memdump_record_biggest(FAR struct mm_memdump_priv_s *priv,
FAR void *ptr, size_t size)
{
if (priv->filled < CONFIG_MM_HEAP_BIGGEST_COUNT)
{
priv->node[priv->filled].ptr = ptr;
priv->node[priv->filled].size = size;
priv->filled++;
}
else
{
if (size <= priv->node[0].size)
{
return;
}
priv->node[0].ptr = ptr;
priv->node[0].size = size;
}
if (priv->filled > 1)
{
qsort(priv->node, priv->filled, sizeof(struct mm_tlsf_node_s),
memdump_record_comare);
}
}
static void memdump_dump_biggestnodes(FAR struct mm_memdump_priv_s *priv)
{
size_t i;
for (i = 0; i < priv->filled; i++)
{
memdump_allocnode(priv->node[i].ptr, priv->node[i].size);
}
}
#endif
#if CONFIG_MM_BACKTRACE >= 0
/****************************************************************************
@ -472,6 +535,12 @@ static void memdump_handler(FAR void *ptr, size_t size, int used,
{
memdump_allocnode(ptr, size);
}
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
else if(dump->pid == PID_MM_BIGGEST && MM_DUMP_SEQNO(dump, buf))
{
memdump_record_biggest(priv, ptr, size);
}
#endif
#undef buf
}
else if (dump->pid == PID_MM_FREE)
@ -1083,6 +1152,20 @@ void mm_memdump(FAR struct mm_heap_s *heap,
syslog(LOG_INFO, "%12s%*s\n", "Size", BACKTRACE_PTR_FMT_WIDTH,
"Address");
}
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
else if (dump->pid == PID_MM_BIGGEST)
{
syslog(LOG_INFO, "Memdump biggest allocated top %d\n",
CONFIG_MM_HEAP_BIGGEST_COUNT);
# if CONFIG_MM_BACKTRACE < 0
syslog(LOG_INFO, "%12s%*s\n", "Size", BACKTRACE_PTR_FMT_WIDTH,
"Address");
# else
syslog(LOG_INFO, "%6s%12s%12s%*s %s\n", "PID", "Size", "Sequence",
BACKTRACE_PTR_FMT_WIDTH, "Address", "Backtrace");
# endif
}
#endif
#ifdef CONFIG_MM_HEAP_MEMPOOL
mempool_multiple_memdump(heap->mm_mpool, dump);
@ -1107,6 +1190,12 @@ void mm_memdump(FAR struct mm_heap_s *heap,
syslog(LOG_INFO, "%12s%12s\n", "Total Blks", "Total Size");
syslog(LOG_INFO, "%12d%12d\n", info.aordblks, info.uordblks);
}
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
else if (dump->pid == PID_MM_BIGGEST)
{
memdump_dump_biggestnodes(&priv);
}
#endif
}
/****************************************************************************