mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 06:42:32 +08:00
memdump: add biggest allocated node dump
Signed-off-by: buxiasen <buxiasen@xiaomi.com>
This commit is contained in:
@@ -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]))
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
Reference in New Issue
Block a user