mirror of
https://github.com/apache/nuttx.git
synced 2026-05-29 04:19:37 +08:00
procfs: add heapcheck flag
1 for open heapcheck, 0 for close echo 1 > /proc/xxx/heapcheck echo 0 > /proc/xxx/heapcheck Signed-off-by: haopengxiang <haopengxiang@xiaomi.com>
This commit is contained in:
+124
-14
@@ -92,6 +92,9 @@ enum proc_node_e
|
|||||||
#endif
|
#endif
|
||||||
#if CONFIG_MM_BACKTRACE >= 0
|
#if CONFIG_MM_BACKTRACE >= 0
|
||||||
PROC_HEAP, /* Task heap info */
|
PROC_HEAP, /* Task heap info */
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_DEBUG_MM
|
||||||
|
PROC_HEAP_CHECK, /* Task heap check flag */
|
||||||
#endif
|
#endif
|
||||||
PROC_STACK, /* Task stack info */
|
PROC_STACK, /* Task stack info */
|
||||||
PROC_GROUP, /* Group directory */
|
PROC_GROUP, /* Group directory */
|
||||||
@@ -183,6 +186,14 @@ static ssize_t proc_heap(FAR struct proc_file_s *procfile,
|
|||||||
FAR struct tcb_s *tcb, FAR char *buffer,
|
FAR struct tcb_s *tcb, FAR char *buffer,
|
||||||
size_t buflen, off_t offset);
|
size_t buflen, off_t offset);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_DEBUG_MM
|
||||||
|
static ssize_t proc_heapcheck(FAR struct proc_file_s *procfile,
|
||||||
|
FAR struct tcb_s *tcb, FAR char *buffer,
|
||||||
|
size_t buflen, off_t offset);
|
||||||
|
static ssize_t proc_heapcheck_write(FAR struct proc_file_s *procfile,
|
||||||
|
FAR struct tcb_s *tcb, FAR const char *buffer,
|
||||||
|
size_t buflen, off_t offset);
|
||||||
|
#endif
|
||||||
static ssize_t proc_stack(FAR struct proc_file_s *procfile,
|
static ssize_t proc_stack(FAR struct proc_file_s *procfile,
|
||||||
FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen,
|
FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen,
|
||||||
off_t offset);
|
off_t offset);
|
||||||
@@ -206,7 +217,8 @@ static int proc_open(FAR struct file *filep, FAR const char *relpath,
|
|||||||
static int proc_close(FAR struct file *filep);
|
static int proc_close(FAR struct file *filep);
|
||||||
static ssize_t proc_read(FAR struct file *filep, FAR char *buffer,
|
static ssize_t proc_read(FAR struct file *filep, FAR char *buffer,
|
||||||
size_t buflen);
|
size_t buflen);
|
||||||
|
static ssize_t proc_write(FAR struct file *filep, FAR const char *buffer,
|
||||||
|
size_t buflen);
|
||||||
static int proc_dup(FAR const struct file *oldp,
|
static int proc_dup(FAR const struct file *oldp,
|
||||||
FAR struct file *newp);
|
FAR struct file *newp);
|
||||||
|
|
||||||
@@ -236,7 +248,7 @@ const struct procfs_operations proc_operations =
|
|||||||
proc_open, /* open */
|
proc_open, /* open */
|
||||||
proc_close, /* close */
|
proc_close, /* close */
|
||||||
proc_read, /* read */
|
proc_read, /* read */
|
||||||
NULL, /* write */
|
proc_write, /* write */
|
||||||
|
|
||||||
proc_dup, /* dup */
|
proc_dup, /* dup */
|
||||||
|
|
||||||
@@ -286,6 +298,13 @@ static const struct proc_node_s g_heap =
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_MM
|
||||||
|
static const struct proc_node_s g_heapcheck =
|
||||||
|
{
|
||||||
|
"heapcheck", "heapcheck", (uint8_t)PROC_HEAP_CHECK, DTYPE_FILE /* Task heap info */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct proc_node_s g_stack =
|
static const struct proc_node_s g_stack =
|
||||||
{
|
{
|
||||||
"stack", "stack", (uint8_t)PROC_STACK, DTYPE_FILE /* Task stack info */
|
"stack", "stack", (uint8_t)PROC_STACK, DTYPE_FILE /* Task stack info */
|
||||||
@@ -328,6 +347,9 @@ static FAR const struct proc_node_s * const g_nodeinfo[] =
|
|||||||
#endif
|
#endif
|
||||||
#if CONFIG_MM_BACKTRACE >= 0
|
#if CONFIG_MM_BACKTRACE >= 0
|
||||||
&g_heap, /* Task heap info */
|
&g_heap, /* Task heap info */
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_DEBUG_MM
|
||||||
|
&g_heapcheck, /* Task heap check flag */
|
||||||
#endif
|
#endif
|
||||||
&g_stack, /* Task stack info */
|
&g_stack, /* Task stack info */
|
||||||
&g_group, /* Group directory */
|
&g_group, /* Group directory */
|
||||||
@@ -354,6 +376,9 @@ static const struct proc_node_s * const g_level0info[] =
|
|||||||
#endif
|
#endif
|
||||||
#if CONFIG_MM_BACKTRACE >= 0
|
#if CONFIG_MM_BACKTRACE >= 0
|
||||||
&g_heap, /* Task heap info */
|
&g_heap, /* Task heap info */
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_DEBUG_MM
|
||||||
|
&g_heapcheck, /* Task heap check flag */
|
||||||
#endif
|
#endif
|
||||||
&g_stack, /* Task stack info */
|
&g_stack, /* Task stack info */
|
||||||
&g_group, /* Group directory */
|
&g_group, /* Group directory */
|
||||||
@@ -952,6 +977,54 @@ static ssize_t proc_heap(FAR struct proc_file_s *procfile,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_MM
|
||||||
|
static ssize_t proc_heapcheck(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;
|
||||||
|
size_t heapcheck = 0;
|
||||||
|
|
||||||
|
if (tcb->flags & TCB_FLAG_HEAPCHECK)
|
||||||
|
{
|
||||||
|
heapcheck = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%d\n",
|
||||||
|
"HeapCheck:", heapcheck);
|
||||||
|
|
||||||
|
copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining,
|
||||||
|
&offset);
|
||||||
|
totalsize += copysize;
|
||||||
|
return totalsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t proc_heapcheck_write(FAR struct proc_file_s *procfile,
|
||||||
|
FAR struct tcb_s *tcb,
|
||||||
|
FAR const char *buffer,
|
||||||
|
size_t buflen, off_t offset)
|
||||||
|
{
|
||||||
|
switch (atoi(buffer))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
tcb->flags &= ~TCB_FLAG_HEAPCHECK;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tcb->flags |= TCB_FLAG_HEAPCHECK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ferr("ERROR: invalid argument\n");
|
||||||
|
return -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buflen;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: proc_stack
|
* Name: proc_stack
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -1407,18 +1480,6 @@ static int proc_open(FAR struct file *filep, FAR const char *relpath,
|
|||||||
|
|
||||||
finfo("Open '%s'\n", relpath);
|
finfo("Open '%s'\n", relpath);
|
||||||
|
|
||||||
/* PROCFS is read-only. Any attempt to open with any kind of write
|
|
||||||
* access is not permitted.
|
|
||||||
*
|
|
||||||
* REVISIT: Write-able proc files could be quite useful.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0)
|
|
||||||
{
|
|
||||||
ferr("ERROR: Only O_RDONLY supported\n");
|
|
||||||
return -EACCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The first segment of the relative path should be a task/thread ID or
|
/* The first segment of the relative path should be a task/thread ID or
|
||||||
* the string "self".
|
* the string "self".
|
||||||
*/
|
*/
|
||||||
@@ -1579,6 +1640,11 @@ static ssize_t proc_read(FAR struct file *filep, FAR char *buffer,
|
|||||||
case PROC_HEAP: /* Task heap info */
|
case PROC_HEAP: /* Task heap info */
|
||||||
ret = proc_heap(procfile, tcb, buffer, buflen, filep->f_pos);
|
ret = proc_heap(procfile, tcb, buffer, buflen, filep->f_pos);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_DEBUG_MM
|
||||||
|
case PROC_HEAP_CHECK: /* Task heap check flag */
|
||||||
|
ret = proc_heapcheck(procfile, tcb, buffer, buflen, filep->f_pos);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
case PROC_STACK: /* Task stack info */
|
case PROC_STACK: /* Task stack info */
|
||||||
ret = proc_stack(procfile, tcb, buffer, buflen, filep->f_pos);
|
ret = proc_stack(procfile, tcb, buffer, buflen, filep->f_pos);
|
||||||
@@ -1613,6 +1679,50 @@ static ssize_t proc_read(FAR struct file *filep, FAR char *buffer,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: proc_write
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static ssize_t proc_write(FAR struct file *filep, FAR const char *buffer,
|
||||||
|
size_t buflen)
|
||||||
|
{
|
||||||
|
FAR struct proc_file_s *procfile;
|
||||||
|
FAR struct tcb_s *tcb;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
DEBUGASSERT(filep != NULL && buffer != NULL && buflen > 0);
|
||||||
|
|
||||||
|
procfile = (FAR struct proc_file_s *)filep->f_priv;
|
||||||
|
DEBUGASSERT(procfile != NULL);
|
||||||
|
|
||||||
|
/* Verify that the thread is still valid */
|
||||||
|
|
||||||
|
tcb = nxsched_get_tcb(procfile->pid);
|
||||||
|
if (tcb == NULL)
|
||||||
|
{
|
||||||
|
ferr("ERROR: PID %d is not valid\n", (int)procfile->pid);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Provide the requested data */
|
||||||
|
|
||||||
|
switch (procfile->node->node)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_DEBUG_MM
|
||||||
|
case PROC_HEAP_CHECK:
|
||||||
|
ret = proc_heapcheck_write(procfile, tcb, buffer, buflen,
|
||||||
|
filep->f_pos);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: proc_dup
|
* Name: proc_dup
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user