Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 124 additions & 14 deletions fs/procfs/fs_procfsproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ enum proc_node_e
#endif
#if CONFIG_MM_BACKTRACE >= 0
PROC_HEAP, /* Task heap info */
#endif
#ifdef CONFIG_DEBUG_MM
PROC_HEAP_CHECK, /* Task heap check flag */
#endif
PROC_STACK, /* Task stack info */
PROC_GROUP, /* Group directory */
Expand Down Expand Up @@ -183,6 +186,14 @@ 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
#ifdef CONFIG_DEBUG_MM
static ssize_t proc_heapcheck(FAR struct proc_file_s *procfile,
Comment thread
xiaoxiang781216 marked this conversation as resolved.
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,
FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen,
off_t offset);
Expand All @@ -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 ssize_t proc_read(FAR struct file *filep, FAR char *buffer,
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,
FAR struct file *newp);

Expand Down Expand Up @@ -236,7 +248,7 @@ const struct procfs_operations proc_operations =
proc_open, /* open */
proc_close, /* close */
proc_read, /* read */
NULL, /* write */
proc_write, /* write */

proc_dup, /* dup */

Expand Down Expand Up @@ -286,6 +298,13 @@ static const struct proc_node_s g_heap =
};
#endif

#ifdef CONFIG_DEBUG_MM
static const struct proc_node_s g_heapcheck =
Comment thread
xiaoxiang781216 marked this conversation as resolved.
{
"heapcheck", "heapcheck", (uint8_t)PROC_HEAP_CHECK, 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 */
Expand Down Expand Up @@ -328,6 +347,9 @@ static FAR const struct proc_node_s * const g_nodeinfo[] =
#endif
#if CONFIG_MM_BACKTRACE >= 0
&g_heap, /* Task heap info */
#endif
#ifdef CONFIG_DEBUG_MM
&g_heapcheck, /* Task heap check flag */
Comment thread
xiaoxiang781216 marked this conversation as resolved.
#endif
&g_stack, /* Task stack info */
&g_group, /* Group directory */
Expand All @@ -354,6 +376,9 @@ static const struct proc_node_s * const g_level0info[] =
#endif
#if CONFIG_MM_BACKTRACE >= 0
&g_heap, /* Task heap info */
#endif
#ifdef CONFIG_DEBUG_MM
&g_heapcheck, /* Task heap check flag */
Comment thread
xiaoxiang781216 marked this conversation as resolved.
#endif
&g_stack, /* Task stack info */
&g_group, /* Group directory */
Expand Down Expand Up @@ -952,6 +977,54 @@ static ssize_t proc_heap(FAR struct proc_file_s *procfile,
}
#endif

#ifdef CONFIG_DEBUG_MM
static ssize_t proc_heapcheck(FAR struct proc_file_s *procfile,
Comment thread
xiaoxiang781216 marked this conversation as resolved.
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
****************************************************************************/
Expand Down Expand Up @@ -1407,18 +1480,6 @@ static int proc_open(FAR struct file *filep, FAR const char *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 string "self".
*/
Expand Down Expand Up @@ -1579,6 +1640,11 @@ static ssize_t proc_read(FAR struct file *filep, FAR char *buffer,
case PROC_HEAP: /* Task heap info */
ret = proc_heap(procfile, tcb, buffer, buflen, filep->f_pos);
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
case PROC_STACK: /* Task stack info */
ret = proc_stack(procfile, tcb, buffer, buflen, filep->f_pos);
Expand Down Expand Up @@ -1613,6 +1679,50 @@ static ssize_t proc_read(FAR struct file *filep, FAR char *buffer,
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
*
Expand Down
2 changes: 1 addition & 1 deletion include/nuttx/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
#define TCB_FLAG_SYSCALL (1 << 10) /* Bit 9: In a system call */
#define TCB_FLAG_EXIT_PROCESSING (1 << 11) /* Bit 10: Exitting */
#define TCB_FLAG_FREE_STACK (1 << 12) /* Bit 12: Free stack after exit */
#define TCB_FLAG_MEM_CHECK (1 << 13) /* Bit 13: Memory check */
#define TCB_FLAG_HEAPCHECK (1 << 13) /* Bit 13: Heap check */
/* Bits 14-15: Available */

/* Values for struct task_group tg_flags */
Expand Down
4 changes: 2 additions & 2 deletions sched/irq/irq_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ void irq_dispatch(int irq, FAR void *context)
#endif

#ifdef CONFIG_DEBUG_MM
if ((g_running_tasks[this_cpu()]->flags & TCB_FLAG_MEM_CHECK) || \
(this_task()->flags & TCB_FLAG_MEM_CHECK))
if ((g_running_tasks[this_cpu()]->flags & TCB_FLAG_HEAPCHECK) || \
(this_task()->flags & TCB_FLAG_HEAPCHECK))
{
kmm_checkcorruption();
}
Expand Down