diff --git a/ChangeLog b/ChangeLog index 521dc32c22..462393b89d 100755 --- a/ChangeLog +++ b/ChangeLog @@ -11459,3 +11459,7 @@ * libc/syslog/lib_syslog.c: If syslog timestamping is enabled, don't try to get the time if the timer hardware has not yet been initialized (2016-02-05). + * fs/procfs/fs_procfskmm.c: Add /proc/kmm entry that shows that state of + the kernel heap. Only useful in PROTECTED and KERNEL build modes where + there is a kernel heap (2016-02-06). + diff --git a/TODO b/TODO index e4b9dfd569..a84666321a 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -NuttX TODO List (Last updated February 2, 2016) +NuttX TODO List (Last updated February 6, 2016) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with @@ -14,8 +14,8 @@ nuttx/ (3) Signals (sched/signal, arch/) (2) pthreads (sched/pthread) (0) Message Queues (sched/mqueue) - (7) Kernel/Protected Build - (4) C++ Support + (6) Kernel/Protected Build + (3) C++ Support (6) Binary loaders (binfmt/) (12) Network (net/, drivers/net) (4) USB (drivers/usbdev, drivers/usbhost) @@ -463,14 +463,6 @@ o Kernel/Protected Build Priority: Medium/High -- the kernel build configuration is not fully fielded yet. - Title: NSH free COMMAND LIMITATION - Description: The NSH 'free' command only shows memory usage in the user - heap only, not usage in the kernel heap. I am thinking that - kernel heap memory usage should be available in /proc/memory. - Better /proc/kmm - Status: Open - Priority: Medium/High - Title: NxTERM PARTITIONING. Description: NxTerm is implemented (correctly) as a driver that resides in the nuttx/ directory. However, the user interfaces must be @@ -590,20 +582,6 @@ o C++ Support would be to get a hold of the compilers definition of size_t. Priority: Low. - Title: STATIC CONSTRUCTORS - Description: Need to call static constructors - Update: Static constructors are implemented for the STM32 F4 and - this will provide the model for all solutions. Basically, if - CONFIG_HAVE_CXXINITIALIZE=y is defined in the configuration, then - board-specific code must provide the interface up_cxxinitialize(). - up_cxxinitialize() is called from application logic to initialize - all static class instances. This TODO item probably has to stay - open because this solution is only available on STM32 F4. - Status: Open - Priority: Low, depends on toolchain. Call to gcc's built-in static - constructor logic will probably have to be performed by - user logic in the application. - Title: STATIC CONSTRUCTORS AND MULTITASKING Description: The logic that calls static constructors operates on the main thread of the initial user application task. Any static diff --git a/fs/procfs/Kconfig b/fs/procfs/Kconfig index 7f3620f9c8..b218c405b9 100644 --- a/fs/procfs/Kconfig +++ b/fs/procfs/Kconfig @@ -48,6 +48,11 @@ config FS_PROCFS_EXCLUDE_CPULOAD default n depends on SCHED_CPULOAD +config FS_PROCFS_EXCLUDE_KMM + bool "Exclude kmm" + default n + depends on MM_KERNEL_HEAP + config FS_PROCFS_EXCLUDE_MOUNTS bool "Exclude mounts" default n diff --git a/fs/procfs/Make.defs b/fs/procfs/Make.defs index 63cd07eb91..434e85799e 100644 --- a/fs/procfs/Make.defs +++ b/fs/procfs/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # fs/procfs/Make.defs # -# Copyright (C) 2013 Gregory Nutt. All rights reserved. +# Copyright (C) 2013, 2016 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -38,7 +38,7 @@ ifeq ($(CONFIG_FS_PROCFS),y) ASRCS += CSRCS += fs_procfs.c fs_procfsutil.c fs_procfsproc.c fs_procfsuptime.c -CSRCS += fs_procfscpuload.c +CSRCS += fs_procfscpuload.c fs_procfskmm.c # Include procfs build support diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c index 8da8842fb4..7f86a17a8d 100644 --- a/fs/procfs/fs_procfs.c +++ b/fs/procfs/fs_procfs.c @@ -1,7 +1,7 @@ /**************************************************************************** * fs/procfs/fs_procfs.c * - * Copyright (C) 2013-2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -77,6 +77,7 @@ extern const struct procfs_operations proc_operations; extern const struct procfs_operations cpuload_operations; +extern const struct procfs_operations kmm_operations; extern const struct procfs_operations module_operations; extern const struct procfs_operations uptime_operations; @@ -120,6 +121,10 @@ static const struct procfs_entry_s g_procfs_entries[] = { "cpuload", &cpuload_operations }, #endif +#if defined(CONFIG_MM_KERNEL_HEAP) && !defined(CONFIG_FS_PROCFS_EXCLUDE_KMM) + { "kmm", &kmm_operations }, +#endif + #if defined(CONFIG_MODULE) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE) { "modules", &module_operations }, #endif diff --git a/fs/procfs/fs_procfskmm.c b/fs/procfs/fs_procfskmm.c new file mode 100644 index 0000000000..edfe3933e8 --- /dev/null +++ b/fs/procfs/fs_procfskmm.c @@ -0,0 +1,326 @@ +/**************************************************************************** + * fs/procfs/fs_procfskmm.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(CONFIG_MM_KERNEL_HEAP) && defined(CONFIG_FS_PROCFS) && \ + !defined(CONFIG_FS_PROCFS_EXCLUDE_KMM) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Determines the size of an intermediate buffer that must be large enough + * to handle the longest line generated by this logic. + */ + +#define KMM_LINELEN 54 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes one open "file" */ + +struct kmm_file_s +{ + struct procfs_file_s base; /* Base open file structure */ + unsigned int linesize; /* Number of valid characters in line[] */ + char line[KMM_LINELEN]; /* Pre-allocated buffer for formatted lines */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* File system methods */ + +static int kmm_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode); +static int kmm_close(FAR struct file *filep); +static ssize_t kmm_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static int kmm_dup(FAR const struct file *oldp, + FAR struct file *newp); +static int kmm_stat(FAR const char *relpath, FAR struct stat *buf); + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* See fs_mount.c -- this structure is explicitly externed there. + * We use the old-fashioned kind of initializers so that this will compile + * with any compiler. + */ + +const struct procfs_operations kmm_operations = +{ + kmm_open, /* open */ + kmm_close, /* close */ + kmm_read, /* read */ + NULL, /* write */ + kmm_dup, /* dup */ + NULL, /* opendir */ + NULL, /* closedir */ + NULL, /* readdir */ + NULL, /* rewinddir */ + kmm_stat /* stat */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: kmm_open + ****************************************************************************/ + +static int kmm_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode) +{ + FAR struct kmm_file_s *procfile; + + fvdbg("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) + { + fdbg("ERROR: Only O_RDONLY supported\n"); + return -EACCES; + } + + /* "kmm" is the only acceptable value for the relpath */ + + if (strcmp(relpath, "kmm") != 0) + { + fdbg("ERROR: relpath is '%s'\n", relpath); + return -ENOENT; + } + + /* Allocate a container to hold the file attributes */ + + procfile = (FAR struct kmm_file_s *)kmm_zalloc(sizeof(struct kmm_file_s)); + if (!procfile) + { + fdbg("ERROR: Failed to allocate file attributes\n"); + return -ENOMEM; + } + + /* Save the attributes as the open-specific state in filep->f_priv */ + + filep->f_priv = (FAR void *)procfile; + return OK; +} + +/**************************************************************************** + * Name: kmm_close + ****************************************************************************/ + +static int kmm_close(FAR struct file *filep) +{ + FAR struct kmm_file_s *procfile; + + /* Recover our private data from the struct file instance */ + + procfile = (FAR struct kmm_file_s *)filep->f_priv; + DEBUGASSERT(procfile); + + /* Release the file attributes structure */ + + kmm_free(procfile); + filep->f_priv = NULL; + return OK; +} + +/**************************************************************************** + * Name: kmm_read + ****************************************************************************/ + +static ssize_t kmm_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct kmm_file_s *procfile; + struct mallinfo mem; + size_t linesize; + size_t copysize; + size_t totalsize; + off_t offset; + + fvdbg("buffer=%p buflen=%d\n", buffer, (int)buflen); + + DEBUGASSERT(filep != NULL && buffer != NULL && buflen > 0); + offset = filep->f_pos; + + /* Recover our private data from the struct file instance */ + + procfile = (FAR struct kmm_file_s *)filep->f_priv; + DEBUGASSERT(procfile); + + /* The first line is the headers */ + + linesize = snprintf(procfile->line, KMM_LINELEN, + " total used free largest\n"); + copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen, + &offset); + totalsize = copysize; + + if (totalsize < buflen) + { + buffer += copysize; + buflen -= copysize; + + /* The second line is the memory data */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + mem = kmm_mallinfo(); +#else + (void)kmm_mallinfo(&mem); +#endif + + linesize = snprintf(procfile->line, KMM_LINELEN, + "Mem: %11d%11d%11d%11d\n", + mem.arena, mem.uordblks, mem.fordblks, + mem.mxordblk); + copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen, + &offset); + totalsize += copysize; + } + + /* Update the file offset */ + + filep->f_pos += totalsize; + return totalsize; +} + +/**************************************************************************** + * Name: kmm_dup + * + * Description: + * Duplicate open file data in the new file structure. + * + ****************************************************************************/ + +static int kmm_dup(FAR const struct file *oldp, FAR struct file *newp) +{ + FAR struct kmm_file_s *oldattr; + FAR struct kmm_file_s *newattr; + + fvdbg("Dup %p->%p\n", oldp, newp); + + /* Recover our private data from the old struct file instance */ + + oldattr = (FAR struct kmm_file_s *)oldp->f_priv; + DEBUGASSERT(oldattr); + + /* Allocate a new container to hold the task and attribute selection */ + + newattr = (FAR struct kmm_file_s *)kmm_malloc(sizeof(struct kmm_file_s)); + if (!newattr) + { + fdbg("ERROR: Failed to allocate file attributes\n"); + return -ENOMEM; + } + + /* The copy the file attributes from the old attributes to the new */ + + memcpy(newattr, oldattr, sizeof(struct kmm_file_s)); + + /* Save the new attributes in the new file structure */ + + newp->f_priv = (FAR void *)newattr; + return OK; +} + +/**************************************************************************** + * Name: kmm_stat + * + * Description: Return information about a file or directory + * + ****************************************************************************/ + +static int kmm_stat(FAR const char *relpath, FAR struct stat *buf) +{ + /* "kmm" is the only acceptable value for the relpath */ + + if (strcmp(relpath, "kmm") != 0) + { + fdbg("ERROR: relpath is '%s'\n", relpath); + return -ENOENT; + } + + /* "kmm" is the name for a read-only file */ + + buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR; + buf->st_size = 0; + buf->st_blksize = 0; + buf->st_blocks = 0; + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* CONFIG_MM_KERNEL_HEAP && CONFIG_FS_PROCFS && !CONFIG_FS_PROCFS_EXCLUDE_KMM */ diff --git a/include/nuttx/mm/mm.h b/include/nuttx/mm/mm.h index a18f12c6fa..7d2e102f31 100644 --- a/include/nuttx/mm/mm.h +++ b/include/nuttx/mm/mm.h @@ -491,8 +491,8 @@ int mm_mallinfo(FAR struct mm_heap_s *heap, FAR struct mallinfo *info); struct mallinfo kmm_mallinfo(void); #else int kmm_mallinfo(struct mallinfo *info); -#endif #endif /* CONFIG_CAN_PASS_STRUCTS */ +#endif /* CONFIG_MM_KERNEL_HEAP */ /* Functions contained in mm_shrinkchunk.c **********************************/