You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/08/09 07:39:05 UTC

[incubator-nuttx] 02/02: fs/procfs: add mempool info to proc/mempool

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit c18b5602e87e5495d7df064e9e254391e632c65b
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Fri Jul 29 04:17:14 2022 +0000

    fs/procfs: add mempool info to proc/mempool
    
    server> cat /proc/mempool
                       total    bsize    nused    nfree   nifree  nwaiter
           hello:        400       20       17        3        0        0
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 fs/procfs/fs_procfs.c       |   5 +
 include/nuttx/mm/mempool.h  |  77 ++++++++++++-
 mm/Kconfig                  |   5 +
 mm/mempool/Make.defs        |  11 ++
 mm/mempool/mempool.c        |  59 +++++++++-
 mm/mempool/mempool_procfs.c | 260 ++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 413 insertions(+), 4 deletions(-)

diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c
index 30b0f074c0..de47d7b006 100644
--- a/fs/procfs/fs_procfs.c
+++ b/fs/procfs/fs_procfs.c
@@ -68,6 +68,7 @@ extern const struct procfs_operations cpuload_operations;
 extern const struct procfs_operations critmon_operations;
 extern const struct procfs_operations meminfo_operations;
 extern const struct procfs_operations memdump_operations;
+extern const struct procfs_operations mempool_operations;
 extern const struct procfs_operations iobinfo_operations;
 extern const struct procfs_operations module_operations;
 extern const struct procfs_operations uptime_operations;
@@ -122,6 +123,10 @@ static const struct procfs_entry_s g_procfs_entries[] =
 #endif
 #endif
 
+#if defined(CONFIG_MM_MEMPOOL) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MEMPOOL)
+  { "mempool",       &mempool_operations,         PROCFS_FILE_TYPE   },
+#endif
+
 #if defined(CONFIG_MM_IOB) && !defined(CONFIG_FS_PROCFS_EXCLUDE_IOBINFO)
   { "iobinfo",       &iobinfo_operations,         PROCFS_FILE_TYPE   },
 #endif
diff --git a/include/nuttx/mm/mempool.h b/include/nuttx/mm/mempool.h
index 6075f324d3..fed167442a 100644
--- a/include/nuttx/mm/mempool.h
+++ b/include/nuttx/mm/mempool.h
@@ -28,6 +28,7 @@
 #include <queue.h>
 #include <sys/types.h>
 
+#include <nuttx/fs/procfs.h>
 #include <nuttx/spinlock.h>
 #include <nuttx/semaphore.h>
 
@@ -35,10 +36,22 @@
  * Public Types
  ****************************************************************************/
 
+#ifndef CONFIG_FS_PROCFS_EXCLUDE_MEMPOOL
+struct mempool_procfs_entry_s
+{
+  FAR const char *name;
+  FAR struct mempool_procfs_entry_s *next;
+};
+#endif
+
 /* This structure describes memory buffer pool */
 
 struct mempool_s
 {
+#ifndef CONFIG_FS_PROCFS_EXCLUDE_MEMPOOL
+  struct mempool_procfs_entry_s procfs; /* The entry of procfs */
+#endif
+
   sq_queue_t list;       /* The free block list in normal mempool */
   sq_queue_t ilist;      /* The free block list in interrupt mempool */
   sq_queue_t elist;      /* The expand block list for normal mempool */
@@ -50,6 +63,16 @@ struct mempool_s
   sem_t      wait;       /* The semaphore of waiter get free block */
 };
 
+struct mempoolinfo_s
+{
+  unsigned long arena;    /* This is the total size of mempool */
+  unsigned long ordblks;  /* This is the number of free blocks for normal mempool */
+  unsigned long iordblks; /* This is the number of free blocks for interrupt mempool */
+  unsigned long aordblks; /* This is the number of used blocks */
+  unsigned long sizeblks; /* This is the size of a mempool blocks */
+  unsigned long nwaiter;  /* This is the number of waiter for mempool */
+};
+
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
@@ -71,6 +94,7 @@ extern "C"
  *
  * Input Parameters:
  *   pool       - Address of the memory pool to be used.
+ *   name       - The name of memory pool.
  *   bsize      - The block size of memory blocks in pool.
  *   ninitial   - The initial count of memory blocks in pool.
  *   nexpand    - The increment count of memory blocks in pool.
@@ -84,8 +108,9 @@ extern "C"
  *
  ****************************************************************************/
 
-int mempool_init(FAR struct mempool_s *pool, size_t bsize, size_t ninitial,
-                 size_t nexpand, size_t ninterrupt);
+int mempool_init(FAR struct mempool_s *pool, FAR const char *name,
+                 size_t bsize, size_t ninitial, size_t nexpand,
+                 size_t ninterrupt);
 
 /****************************************************************************
  * Name: mempool_alloc
@@ -119,6 +144,22 @@ FAR void *mempool_alloc(FAR struct mempool_s *pool);
 
 void mempool_free(FAR struct mempool_s *pool, FAR void *blk);
 
+/****************************************************************************
+ * Name: mempool_info
+ *
+ * Description:
+ *   mempool_info returns a copy of updated current mempool information.
+ *
+ * Input Parameters:
+ *   pool    - Address of the memory pool to be used.
+ *   info    - The pointer of mempoolinfo.
+ *
+ * Returned Value:
+ *   OK on success; A negated errno value on any failure.
+ ****************************************************************************/
+
+int mempool_info(FAR struct mempool_s *pool, FAR struct mempoolinfo_s *info);
+
 /****************************************************************************
  * Name: mempool_deinit
  *
@@ -131,6 +172,38 @@ void mempool_free(FAR struct mempool_s *pool, FAR void *blk);
 
 int mempool_deinit(FAR struct mempool_s *pool);
 
+/****************************************************************************
+ * Name: mempool_procfs_register
+ *
+ * Description:
+ *   Add a new mempool entry to the procfs file system.
+ *
+ * Input Parameters:
+ *   entry - Describes the entry to be registered.
+ *   name  - The name of mempool.
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_FS_PROCFS_EXCLUDE_MEMPOOL
+void mempool_procfs_register(FAR struct mempool_procfs_entry_s *entry,
+                             FAR const char *name);
+#endif
+
+/****************************************************************************
+ * Name: mempool_procfs_unregister
+ *
+ * Description:
+ *   Remove a mempool entry from the procfs file system.
+ *
+ * Input Parameters:
+ *   entry - Describes the entry to be unregistered.
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_FS_PROCFS_EXCLUDE_MEMPOOL
+void mempool_procfs_unregister(FAR struct mempool_procfs_entry_s *entry);
+#endif
+
 #undef EXTERN
 #if defined(__cplusplus)
 }
diff --git a/mm/Kconfig b/mm/Kconfig
index c8c6df5f65..2ab31daa70 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -178,6 +178,11 @@ config MM_MEMPOOL
 		Memory buffer pool support. Such pools are mostly used
 		for guaranteed, deadlock-free memory allocations.
 
+config FS_PROCFS_EXCLUDE_MEMPOOL
+	bool "Exclude mempool"
+	default n
+	depends on FS_PROCFS
+
 config MM_KASAN
 	bool "Kernel Address Sanitizer"
 	default n
diff --git a/mm/mempool/Make.defs b/mm/mempool/Make.defs
index cda9195fed..6f3dca5479 100644
--- a/mm/mempool/Make.defs
+++ b/mm/mempool/Make.defs
@@ -21,8 +21,19 @@
 # Memory buffer pool management
 
 ifeq ($(CONFIG_MM_MEMPOOL),y)
+
 CSRCS += mempool.c
 
+ifeq ($(CONFIG_FS_PROCFS),y)
+
+ifneq ($(CONFIG_FS_PROCFS_EXCLUDE_MEMPOOL),y)
+
+CSRCS += mempool_procfs.c
+
+endif
+
+endif
+
 # Add the memory buffer pool directory to the build
 
 DEPPATH += --dep-path mempool
diff --git a/mm/mempool/mempool.c b/mm/mempool/mempool.c
index 5076556518..40057c6aff 100644
--- a/mm/mempool/mempool.c
+++ b/mm/mempool/mempool.c
@@ -53,6 +53,7 @@ static inline void mempool_add_list(FAR sq_queue_t *list, FAR void *base,
  *
  * Input Parameters:
  *   pool       - Address of the memory pool to be used.
+ *   name       - The name of memory pool.
  *   bsize      - The block size of memory blocks in pool.
  *   ninitial   - The initial count of memory blocks in pool.
  *   nexpand    - The increment count of memory blocks in pool.
@@ -66,8 +67,9 @@ static inline void mempool_add_list(FAR sq_queue_t *list, FAR void *base,
  *
  ****************************************************************************/
 
-int mempool_init(FAR struct mempool_s *pool, size_t bsize, size_t ninitial,
-                 size_t nexpand, size_t ninterrupt)
+int mempool_init(FAR struct mempool_s *pool, FAR const char *name,
+                 size_t bsize, size_t ninitial, size_t nexpand,
+                 size_t ninterrupt)
 {
   size_t count = ninitial + ninterrupt;
 
@@ -102,6 +104,10 @@ int mempool_init(FAR struct mempool_s *pool, size_t bsize, size_t ninitial,
   nxsem_init(&pool->wait, 0, 0);
   nxsem_set_protocol(&pool->wait, SEM_PRIO_NONE);
 
+#ifndef CONFIG_FS_PROCFS_EXCLUDE_MEMPOOL
+  mempool_procfs_register(&pool->procfs, name);
+#endif
+
   return 0;
 }
 
@@ -227,6 +233,51 @@ void mempool_free(FAR struct mempool_s *pool, FAR void *blk)
     }
 }
 
+/****************************************************************************
+ * Name: mempool_info
+ *
+ * Description:
+ *   mempool_info returns a copy of updated current mempool information.
+ *
+ * Input Parameters:
+ *   pool    - Address of the memory pool to be used.
+ *   info    - The pointer of mempoolinfo.
+ *
+ * Returned Value:
+ *   OK on success; A negated errno value on any failure.
+ ****************************************************************************/
+
+int mempool_info(FAR struct mempool_s *pool, FAR struct mempoolinfo_s *info)
+{
+  irqstate_t flags;
+
+  if (pool == NULL || info == NULL)
+    {
+      return -EINVAL;
+    }
+
+  flags = spin_lock_irqsave(&pool->lock);
+  info->ordblks = sq_count(&pool->list);
+  info->iordblks = sq_count(&pool->ilist);
+  info->aordblks = pool->nused;
+  info->arena = (pool->nused + info->ordblks + info->iordblks) * pool->bsize;
+  spin_unlock_irqrestore(&pool->lock, flags);
+  info->sizeblks = pool->bsize;
+  if (pool->nexpand == 0)
+    {
+      int semcount;
+
+      nxsem_get_value(&pool->wait, &semcount);
+      info->nwaiter = -semcount;
+    }
+  else
+    {
+      info->nwaiter = 0;
+    }
+
+  return 0;
+}
+
 /****************************************************************************
  * Name: mempool_deinit
  *
@@ -251,6 +302,10 @@ int mempool_deinit(FAR struct mempool_s *pool)
       return -EBUSY;
     }
 
+#ifndef CONFIG_FS_PROCFS_EXCLUDE_MEMPOOL
+  mempool_procfs_unregister(&pool->procfs);
+#endif
+
   while ((blk = sq_remfirst(&pool->elist)) != NULL)
     {
       kmm_free(blk);
diff --git a/mm/mempool/mempool_procfs.c b/mm/mempool/mempool_procfs.c
new file mode 100644
index 0000000000..df9bc917a0
--- /dev/null
+++ b/mm/mempool/mempool_procfs.c
@@ -0,0 +1,260 @@
+/****************************************************************************
+ * mm/mempool/mempool_procfs.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mm/mempool.h>
+#include <nuttx/fs/procfs.h>
+
+/****************************************************************************
+ * 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 MEMPOOLINFO_LINELEN 80
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure describes one open "file" */
+
+struct mempool_file_s
+{
+  struct procfs_file_s base;      /* Base open file structure */
+  unsigned int linesize;          /* Number of valid characters in line[] */
+  char line[MEMPOOLINFO_LINELEN]; /* Pre-allocated buffer for formatted lines */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int     mempool_open(FAR struct file *filep, FAR const char *relpath,
+                            int oflags, mode_t mode);
+static int     mempool_close(FAR struct file *filep);
+static int     mempool_dup(FAR const struct file *oldp,
+                           FAR struct file *newp);
+static int     mempool_stat(FAR const char *relpath, FAR struct stat *buf);
+static ssize_t mempool_read(FAR struct file *filep, FAR char *buffer,
+                            size_t buflen);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct procfs_operations mempool_operations =
+{
+  mempool_open,   /* open */
+  mempool_close,  /* close */
+  mempool_read,   /* read */
+  NULL,           /* write */
+  mempool_dup,    /* dup */
+  NULL,           /* opendir */
+  NULL,           /* closedir */
+  NULL,           /* readdir */
+  NULL,           /* rewinddir */
+  mempool_stat    /* stat */
+};
+
+static FAR struct mempool_procfs_entry_s *g_mempool_procfs = NULL;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mempool_open
+ ****************************************************************************/
+
+static int mempool_open(FAR struct file *filep, FAR const char *relpath,
+                        int oflags, mode_t mode)
+{
+  FAR struct mempool_file_s *procfile;
+
+  procfile = kmm_zalloc(sizeof(struct mempool_file_s));
+  if (procfile == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  filep->f_priv = procfile;
+  return 0;
+}
+
+/****************************************************************************
+ * Name: mempool_close
+ ****************************************************************************/
+
+static int mempool_close(FAR struct file *filep)
+{
+  kmm_free(filep->f_priv);
+  filep->f_priv = NULL;
+  return 0;
+}
+
+/****************************************************************************
+ * Name: mempool_read
+ ****************************************************************************/
+
+static ssize_t mempool_read(FAR struct file *filep, FAR char *buffer,
+                            size_t buflen)
+{
+  FAR const struct mempool_procfs_entry_s *entry;
+  FAR struct mempool_file_s *procfile;
+  size_t linesize;
+  size_t copysize;
+  size_t totalsize;
+  off_t offset;
+
+  offset    = filep->f_pos;
+  procfile  = filep->f_priv;
+  linesize  = procfs_snprintf(procfile->line, MEMPOOLINFO_LINELEN,
+                              "%13s%11s%9s%9s%9s%9s%9s\n", "", "total",
+                              "bsize", "nused", "nfree", "nifree",
+                              "nwaiter");
+
+  copysize  = procfs_memcpy(procfile->line, linesize, buffer, buflen,
+                            &offset);
+  totalsize = copysize;
+
+  for (entry = g_mempool_procfs; entry != NULL; entry = entry->next)
+    {
+      if (totalsize < buflen)
+        {
+          struct mempoolinfo_s minfo;
+
+          buffer    += copysize;
+          buflen    -= copysize;
+
+          mempool_info((FAR struct mempool_s *)entry, &minfo);
+          linesize   = procfs_snprintf(procfile->line, MEMPOOLINFO_LINELEN,
+                                       "%12s:%11lu%9lu%9lu%9lu%9lu%9lu\n",
+                                       entry->name, minfo.arena,
+                                       minfo.sizeblks, minfo.aordblks,
+                                       minfo.ordblks, minfo.iordblks,
+                                       minfo.nwaiter);
+          copysize   = procfs_memcpy(procfile->line, linesize, buffer,
+                                     buflen, &offset);
+          totalsize += copysize;
+        }
+    }
+
+  filep->f_pos += totalsize;
+  return totalsize;
+}
+
+/****************************************************************************
+ * Name: mempool_dup
+ *
+ * Description:
+ *   Duplicate open file data in the new file structure.
+ *
+ ****************************************************************************/
+
+static int mempool_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+  FAR struct mempool_file_s *oldattr;
+  FAR struct mempool_file_s *newattr;
+
+  oldattr = oldp->f_priv;
+  newattr = kmm_malloc(sizeof(struct mempool_file_s));
+  if (newattr == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  memcpy(newattr, oldattr, sizeof(struct mempool_file_s));
+  newp->f_priv = newattr;
+  return 0;
+}
+
+/****************************************************************************
+ * Name: mempool_stat
+ *
+ * Description: Return information about a file or directory
+ *
+ ****************************************************************************/
+
+static int mempool_stat(FAR const char *relpath, FAR struct stat *buf)
+{
+  memset(buf, 0, sizeof(struct stat));
+  buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
+  return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mempool_procfs_register
+ *
+ * Description:
+ *   Add a new mempool entry to the procfs file system.
+ *
+ * Input Parameters:
+ *   entry - Describes the entry to be registered.
+ *
+ ****************************************************************************/
+
+void mempool_procfs_register(FAR struct mempool_procfs_entry_s *entry,
+                             FAR const char *name)
+{
+  entry->name = name;
+  entry->next = g_mempool_procfs;
+  g_mempool_procfs = entry;
+}
+
+/****************************************************************************
+ * Name: mempool_procfs_unregister
+ *
+ * Description:
+ *   Remove a mempool entry from the procfs file system.
+ *
+ * Input Parameters:
+ *   entry - Describes the entry to be unregistered.
+ *
+ ****************************************************************************/
+
+void mempool_procfs_unregister(FAR struct mempool_procfs_entry_s *entry)
+{
+  FAR struct mempool_procfs_entry_s **cur;
+
+  for (cur = &g_mempool_procfs; *cur != NULL; cur = &(*cur)->next)
+    {
+      if (*cur == entry)
+        {
+          *cur = entry->next;
+          break;
+        }
+    }
+}