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;
+ }
+ }
+}