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
+27
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 #if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD > 0
"/mempool" "/mempool"
#endif #endif
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
"/biggest"
#endif
#if CONFIG_MM_BACKTRACE > 0 #if CONFIG_MM_BACKTRACE > 0
"/on/off" "/on/off"
#endif #endif
@@ -446,6 +449,9 @@ static ssize_t memdump_read(FAR struct file *filep, FAR char *buffer,
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD > 0 #if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD > 0
"mempool: dump all mempool alloc node\n" "mempool: dump all mempool alloc node\n"
#endif #endif
#if CONFIG_MM_HEAP_BIGGEST_COUNT > 0
"biggest: dump allocated top n node\n"
#endif
#if CONFIG_MM_BACKTRACE > 0 #if CONFIG_MM_BACKTRACE > 0
"on/off: set backtrace enabled state\n" "on/off: set backtrace enabled state\n"
#endif #endif
@@ -573,6 +579,27 @@ static ssize_t memdump_write(FAR struct file *filep, FAR const char *buffer,
break; break;
#endif #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 #if CONFIG_MM_BACKTRACE >= 0
default: default:
if (!isdigit(buffer[0])) if (!isdigit(buffer[0]))
+1
View File
@@ -35,6 +35,7 @@
/* Special PID to query the info about alloc, free and mempool */ /* 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_FREE ((pid_t)-4)
#define PID_MM_ALLOC ((pid_t)-3) #define PID_MM_ALLOC ((pid_t)-3)
#define PID_MM_LEAK ((pid_t)-2) #define PID_MM_LEAK ((pid_t)-2)
+8
View File
@@ -463,4 +463,12 @@ config MM_FREE_DELAYCOUNT_MAX
the value decides the maximum number of memory nodes that the value decides the maximum number of memory nodes that
will be delayed to free. 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" source "mm/iob/Kconfig"
+81
View File
@@ -43,10 +43,19 @@
* Private Types * 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 struct mm_memdump_priv_s
{ {
FAR const struct mm_memdump_s *dump; FAR const struct mm_memdump_s *dump;
}; };
#endif
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
@@ -77,6 +86,52 @@ static void memdump_allocnode(FAR struct mm_allocnode_s *node)
#endif #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) static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
{ {
FAR struct mm_memdump_priv_s *priv = 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); 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) 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, syslog(LOG_INFO, "%12s%*s\n", "Size", BACKTRACE_PTR_FMT_WIDTH,
"Address"); "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 #ifdef CONFIG_MM_HEAP_MEMPOOL
mempool_multiple_memdump(heap->mm_mpool, dump); 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, "%12s%12s\n", "Total Blks", "Total Size");
syslog(LOG_INFO, "%12d%12d\n", info.aordblks, info.uordblks); 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
} }
+89
View File
@@ -131,10 +131,25 @@ struct mm_mallinfo_handler_s
FAR struct mallinfo_task *info; 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 struct mm_memdump_priv_s
{ {
FAR const struct mm_memdump_s *dump; FAR const struct mm_memdump_s *dump;
}; };
#endif
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
@@ -168,6 +183,54 @@ static void memdump_allocnode(FAR void *ptr, size_t size)
#endif #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 #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); 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 #undef buf
} }
else if (dump->pid == PID_MM_FREE) 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, syslog(LOG_INFO, "%12s%*s\n", "Size", BACKTRACE_PTR_FMT_WIDTH,
"Address"); "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 #ifdef CONFIG_MM_HEAP_MEMPOOL
mempool_multiple_memdump(heap->mm_mpool, dump); 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, "%12s%12s\n", "Total Blks", "Total Size");
syslog(LOG_INFO, "%12d%12d\n", info.aordblks, info.uordblks); 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
} }
/**************************************************************************** /****************************************************************************