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 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
Jiuzhu Dong 2022-07-29 04:17:14 +00:00 committed by Xiang Xiao
parent e3bbbfe4d0
commit c18b5602e8
6 changed files with 413 additions and 4 deletions

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -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);

260
mm/mempool/mempool_procfs.c Normal file
View File

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