memdump: add biggest allocated node dump
Signed-off-by: buxiasen <buxiasen@xiaomi.com>
This commit is contained in:
parent
fd6634ecb5
commit
fd9a9f67cc
5 changed files with 206 additions and 0 deletions
|
@ -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]))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
Loading…
Reference in a new issue