diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c index ea00c14e8d..097610f137 100644 --- a/fs/procfs/fs_procfsproc.c +++ b/fs/procfs/fs_procfsproc.c @@ -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 */ @@ -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, + 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); @@ -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); @@ -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 */ @@ -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 = +{ + "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 */ @@ -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 */ #endif &g_stack, /* Task stack info */ &g_group, /* Group directory */ @@ -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 */ #endif &g_stack, /* Task stack info */ &g_group, /* Group directory */ @@ -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, + 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 ****************************************************************************/ @@ -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". */ @@ -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); @@ -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 *