diff --git a/fs/procfs/fs_procfsmeminfo.c b/fs/procfs/fs_procfsmeminfo.c index 5dabecb96a0..ada57edff18 100644 --- a/fs/procfs/fs_procfsmeminfo.c +++ b/fs/procfs/fs_procfsmeminfo.c @@ -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])) diff --git a/include/malloc.h b/include/malloc.h index 8168cd68a29..ccae9330a0a 100644 --- a/include/malloc.h +++ b/include/malloc.h @@ -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) diff --git a/mm/Kconfig b/mm/Kconfig index 764be1b08e1..ecfb7268d35 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -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" diff --git a/mm/mm_heap/mm_memdump.c b/mm/mm_heap/mm_memdump.c index e98cd73b5f9..0735730e0c1 100644 --- a/mm/mm_heap/mm_memdump.c +++ b/mm/mm_heap/mm_memdump.c @@ -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 } diff --git a/mm/tlsf/mm_tlsf.c b/mm/tlsf/mm_tlsf.c index c9f32cc8372..cae168a9c4b 100644 --- a/mm/tlsf/mm_tlsf.c +++ b/mm/tlsf/mm_tlsf.c @@ -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 } /****************************************************************************