From 7ae3c572dc8475e9ef2d6b05e2dc62c99f5203ca Mon Sep 17 00:00:00 2001 From: Jiuzhu Dong Date: Sat, 22 Jan 2022 20:21:51 +0800 Subject: [PATCH] procfs: add heap info for every task cat /proc/2/heap AllocSize: 512 AllocBlks: 10 Signed-off-by: Jiuzhu Dong --- fs/procfs/fs_procfsproc.c | 80 ++++++++++++++++++++++++++++++++++++++ include/malloc.h | 12 ++++++ include/nuttx/mm/mm.h | 8 ++++ mm/kmm_heap/kmm_mallinfo.c | 19 +++++++++ mm/mm_heap/mm_mallinfo.c | 42 ++++++++++++++++++++ mm/umm_heap/umm_mallinfo.c | 20 ++++++++++ 6 files changed, 181 insertions(+) diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c index 60ca146d23..fbf622f1f6 100644 --- a/fs/procfs/fs_procfsproc.c +++ b/fs/procfs/fs_procfsproc.c @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef CONFIG_SCHED_CRITMONITOR # include @@ -50,6 +51,7 @@ #include #include #include +#include #if defined(CONFIG_SCHED_CPULOAD) || defined(CONFIG_SCHED_CRITMONITOR) # include @@ -86,6 +88,9 @@ enum proc_node_e #endif #ifdef CONFIG_SCHED_CRITMONITOR PROC_CRITMON, /* Critical section monitor */ +#endif +#ifdef CONFIG_DEBUG_MM + PROC_HEAP, /* Task heap info */ #endif PROC_STACK, /* Task stack info */ PROC_GROUP, /* Group directory */ @@ -172,6 +177,11 @@ static ssize_t proc_critmon(FAR struct proc_file_s *procfile, FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen, off_t offset); #endif +#ifdef CONFIG_DEBUG_MM +static ssize_t proc_heap(FAR struct proc_file_s *procfile, + FAR struct tcb_s *tcb, FAR char *buffer, + size_t buflen, off_t offset); +#endif static ssize_t proc_stack(FAR struct proc_file_s *procfile, FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen, off_t offset); @@ -268,6 +278,13 @@ static const struct proc_node_s g_critmon = }; #endif +#ifdef CONFIG_DEBUG_MM +static const struct proc_node_s g_heap = +{ + "heap", "heap", (uint8_t)PROC_HEAP, DTYPE_FILE /* Task heap info */ +}; +#endif + static const struct proc_node_s g_stack = { "stack", "stack", (uint8_t)PROC_STACK, DTYPE_FILE /* Task stack info */ @@ -307,6 +324,9 @@ static FAR const struct proc_node_s * const g_nodeinfo[] = #endif #ifdef CONFIG_SCHED_CRITMONITOR &g_critmon, /* Critical section Monitor */ +#endif +#ifdef CONFIG_DEBUG_MM + &g_heap, /* Task heap info */ #endif &g_stack, /* Task stack info */ &g_group, /* Group directory */ @@ -330,6 +350,9 @@ static const struct proc_node_s * const g_level0info[] = #endif #ifdef CONFIG_SCHED_CRITMONITOR &g_critmon, /* Critical section monitor */ +#endif +#ifdef CONFIG_DEBUG_MM + &g_heap, /* Task heap info */ #endif &g_stack, /* Task stack info */ &g_group, /* Group directory */ @@ -876,6 +899,58 @@ static ssize_t proc_critmon(FAR struct proc_file_s *procfile, } #endif +/**************************************************************************** + * Name: proc_heap + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_MM +static ssize_t proc_heap(FAR struct proc_file_s *procfile, + FAR struct tcb_s *tcb, FAR char *buffer, + size_t buflen, off_t offset) +{ + size_t remaining = buflen; + size_t linesize; + size_t copysize; + size_t totalsize = 0; + struct mallinfo_task info; + +#ifdef CONFIG_MM_KERNEL_HEAP + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL) + { + info = kmm_mallinfo_task(tcb->pid); + } + else +#endif + { + info = mallinfo_task(tcb->pid); + } + + /* Show the heap alloc size */ + + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "%-12s%d\n", "AllocSize:", info.uordblks); + copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, + &offset); + + totalsize += copysize; + buffer += copysize; + remaining -= copysize; + + if (totalsize >= buflen) + { + return totalsize; + } + + /* Show the heap alloc block */ + + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, + "%-12s%d\n", "AllocBlks:", info.aordblks); + totalsize += procfs_memcpy(procfile->line, linesize, buffer, remaining, + &offset); + return totalsize; +} +#endif + /**************************************************************************** * Name: proc_stack ****************************************************************************/ @@ -1483,6 +1558,11 @@ static ssize_t proc_read(FAR struct file *filep, FAR char *buffer, case PROC_CRITMON: /* Critical section monitor */ ret = proc_critmon(procfile, tcb, buffer, buflen, filep->f_pos); break; +#endif +#ifdef CONFIG_DEBUG_MM + case PROC_HEAP: /* Task heap info */ + ret = proc_heap(procfile, tcb, buffer, buflen, filep->f_pos); + break; #endif case PROC_STACK: /* Task stack info */ ret = proc_stack(procfile, tcb, buffer, buflen, filep->f_pos); diff --git a/include/malloc.h b/include/malloc.h index 0854174ad4..50345c3233 100644 --- a/include/malloc.h +++ b/include/malloc.h @@ -52,6 +52,15 @@ struct mallinfo * by free (not in use) chunks. */ }; +#ifdef CONFIG_DEBUG_MM +struct mallinfo_task +{ + pid_t pid; /* The pid of task */ + int aordblks; /* This is the number of allocated (in use) chunks for task */ + int uordblks; /* This is the total size of memory occupied for task */ +}; +#endif + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -63,6 +72,9 @@ extern "C" struct mallinfo mallinfo(void); size_t malloc_size(FAR void *ptr); +#ifdef CONFIG_DEBUG_MM +struct mallinfo_task mallinfo_task(pid_t pid); +#endif #if defined(__cplusplus) } diff --git a/include/nuttx/mm/mm.h b/include/nuttx/mm/mm.h index aad4e6f273..6f78a6a607 100644 --- a/include/nuttx/mm/mm.h +++ b/include/nuttx/mm/mm.h @@ -296,11 +296,19 @@ void kmm_extend(FAR void *mem, size_t size, int region); struct mallinfo; /* Forward reference */ int mm_mallinfo(FAR struct mm_heap_s *heap, FAR struct mallinfo *info); +#ifdef CONFIG_DEBUG_MM +struct mallinfo_task; /* Forward reference */ +int mm_mallinfo_task(FAR struct mm_heap_s *heap, + FAR struct mallinfo_task *info); +#endif /* Functions contained in kmm_mallinfo.c ************************************/ #ifdef CONFIG_MM_KERNEL_HEAP struct mallinfo kmm_mallinfo(void); +# ifdef CONFIG_DEBUG_MM +struct mallinfo_task kmm_mallinfo_task(pid_t pid); +# endif #endif /* Functions contained in mm_memdump.c **************************************/ diff --git a/mm/kmm_heap/kmm_mallinfo.c b/mm/kmm_heap/kmm_mallinfo.c index 1172ed4db4..33dd6649c8 100644 --- a/mm/kmm_heap/kmm_mallinfo.c +++ b/mm/kmm_heap/kmm_mallinfo.c @@ -50,4 +50,23 @@ struct mallinfo kmm_mallinfo(void) return info; } +/**************************************************************************** + * Name: kmm_mallinfo_task + * + * Description: + * kmm_mallinfo_task returns a copy of updated current heap information of + * task with specified pid for the user heap. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_MM +struct mallinfo_task kmm_mallinfo_task(pid_t pid) +{ + struct mallinfo_task info; + + info.pid = pid; + mm_mallinfo_task(g_kmmheap, &info); + return info; +} +#endif #endif /* CONFIG_MM_KERNEL_HEAP */ diff --git a/mm/mm_heap/mm_mallinfo.c b/mm/mm_heap/mm_mallinfo.c index e3fb94a1a3..7ecdc039e3 100644 --- a/mm/mm_heap/mm_mallinfo.c +++ b/mm/mm_heap/mm_mallinfo.c @@ -75,6 +75,26 @@ static void mallinfo_handler(FAR struct mm_allocnode_s *node, FAR void *arg) } } +#ifdef CONFIG_DEBUG_MM +static void mallinfo_task_handler(FAR struct mm_allocnode_s *node, + FAR void *arg) +{ + FAR struct mallinfo_task *info = arg; + + /* Check if the node corresponds to an allocated memory chunk */ + + if ((node->preceding & MM_ALLOC_BIT) != 0) + { + DEBUGASSERT(node->size >= SIZEOF_MM_ALLOCNODE); + if (node->pid == info->pid) + { + info->aordblks++; + info->uordblks += node->size; + } + } +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -107,3 +127,25 @@ int mm_mallinfo(FAR struct mm_heap_s *heap, FAR struct mallinfo *info) return OK; } + +/**************************************************************************** + * Name: mm_mallinfo_task + * + * Description: + * mallinfo returns a copy of updated current heap information for task + * with pid. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_MM +int mm_mallinfo_task(FAR struct mm_heap_s *heap, + FAR struct mallinfo_task *info) +{ + DEBUGASSERT(info); + + info->uordblks = 0; + info->aordblks = 0; + mm_foreach(heap, mallinfo_task_handler, info); + return OK; +} +#endif diff --git a/mm/umm_heap/umm_mallinfo.c b/mm/umm_heap/umm_mallinfo.c index 2176095b2a..e59cfa8eac 100644 --- a/mm/umm_heap/umm_mallinfo.c +++ b/mm/umm_heap/umm_mallinfo.c @@ -49,3 +49,23 @@ struct mallinfo mallinfo(void) mm_mallinfo(USR_HEAP, &info); return info; } + +/**************************************************************************** + * Name: mallinfo_task + * + * Description: + * mallinfo_task returns a copy of updated current heap information of + * task with specified pid for the user heap. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_MM +struct mallinfo_task mallinfo_task(pid_t pid) +{ + struct mallinfo_task info; + + info.pid = pid; + mm_mallinfo_task(USR_HEAP, &info); + return info; +} +#endif