procfs: add heap info for every task

cat /proc/2/heap
AllocSize:  512
AllocBlks:  10

Signed-off-by: Jiuzhu Dong <dongjiuzhu1@xiaomi.com>
This commit is contained in:
Jiuzhu Dong 2022-01-22 20:21:51 +08:00 committed by Xiang Xiao
parent 2dcc4a359d
commit 7ae3c572dc
6 changed files with 181 additions and 0 deletions

View File

@ -37,6 +37,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <malloc.h>
#ifdef CONFIG_SCHED_CRITMONITOR
# include <time.h>
@ -50,6 +51,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/fs/procfs.h>
#include <nuttx/fs/dirent.h>
#include <nuttx/mm/mm.h>
#if defined(CONFIG_SCHED_CPULOAD) || defined(CONFIG_SCHED_CRITMONITOR)
# include <nuttx/clock.h>
@ -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);

View File

@ -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)
}

View File

@ -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 **************************************/

View File

@ -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 */

View File

@ -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

View File

@ -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