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 2023/01/18 06:12:55 UTC

[nuttx] 04/06: mempool:use single queue insdie of list

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/nuttx.git

commit 49ffd99eafadfba2122958642d2c9ca9c187e491
Author: anjiahao <an...@xiaomi.com>
AuthorDate: Sat Nov 26 00:22:12 2022 +0800

    mempool:use single queue insdie of list
    
    Signed-off-by: anjiahao <an...@xiaomi.com>
    Signed-off-by: dongjiuzhu1 <do...@xiaomi.com>
---
 include/nuttx/mm/mempool.h    |  16 +--
 mm/mempool/mempool.c          | 260 +++++++++++++++++++++++++-----------------
 mm/mempool/mempool_multiple.c |  17 +--
 3 files changed, 166 insertions(+), 127 deletions(-)

diff --git a/include/nuttx/mm/mempool.h b/include/nuttx/mm/mempool.h
index 0309c4224b..ca9fb7b71a 100644
--- a/include/nuttx/mm/mempool.h
+++ b/include/nuttx/mm/mempool.h
@@ -29,6 +29,7 @@
 #include <sys/types.h>
 
 #include <nuttx/list.h>
+#include <nuttx/queue.h>
 #include <nuttx/fs/procfs.h>
 #include <nuttx/spinlock.h>
 #include <nuttx/semaphore.h>
@@ -74,13 +75,15 @@ struct mempool_s
 
   /* Private data for memory pool */
 
-  struct list_node list;    /* The free block list in normal mempool */
-  struct list_node ilist;   /* The free block list in interrupt mempool */
-  struct list_node elist;   /* The expand block list for normal mempool */
+  FAR char  *ibase;   /* The inerrupt mempool base pointer */
+  sq_queue_t queue;   /* The free block queue in normal mempool */
+  sq_queue_t iqueue;  /* The free block queue in interrupt mempool */
+  sq_queue_t equeue;  /* The expand block queue for normal mempool */
 #if CONFIG_MM_BACKTRACE >= 0
   struct list_node alist;   /* The used block list in mempool */
+#else
+  size_t           nalloc;  /* The number of used block in mempool */
 #endif
-  size_t           nused;   /* The number of used block in mempool */
   spinlock_t       lock;    /* The protect lock to mempool */
   sem_t            waitsem; /* The semaphore of waiter get free block */
 #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MEMPOOL)
@@ -433,12 +436,9 @@ void mempool_multiple_memdump(FAR struct mempool_multiple_s *mpool,
  * Input Parameters:
  *   mpool - The handle of multiple memory pool to be used.
  *
- * Returned Value:
- *   Zero on success; A negated errno value is returned on any failure.
- *
  ****************************************************************************/
 
-int mempool_multiple_deinit(FAR struct mempool_multiple_s *mpool);
+void mempool_multiple_deinit(FAR struct mempool_multiple_s *mpool);
 
 /****************************************************************************
  * Name: mempool_multiple_info_task
diff --git a/mm/mempool/mempool.c b/mm/mempool/mempool.c
index 86add5fc07..4cd9c77184 100644
--- a/mm/mempool/mempool.c
+++ b/mm/mempool/mempool.c
@@ -61,14 +61,40 @@ struct mempool_backtrace_s
  * Private Functions
  ****************************************************************************/
 
-static inline void mempool_add_list(FAR struct list_node *list,
-                                    FAR void *base, size_t nblks,
-                                    size_t blocksize)
+static inline FAR sq_entry_t *mempool_remove_queue(FAR sq_queue_t *queue)
+{
+  if (!sq_empty(queue))
+    {
+      FAR sq_entry_t *entry = queue->head;
+
+      queue->head = entry->flink;
+      return entry;
+    }
+  else
+    {
+      return NULL;
+    }
+}
+
+static inline size_t mempool_queue_lenth(FAR sq_queue_t *queue)
+{
+  FAR sq_entry_t *node;
+  size_t count;
+
+  for (node = queue->head, count = 0;
+       node != NULL;
+       node = node->flink, count++);
+
+  return count;
+}
+
+static inline void mempool_add_queue(FAR sq_queue_t *queue,
+                                     FAR char *base, size_t nblks,
+                                     size_t blocksize)
 {
   while (nblks-- > 0)
     {
-      list_add_head(list, ((FAR struct list_node *)((FAR char *)base +
-                                                    blocksize * nblks)));
+      sq_addfirst((FAR sq_entry_t *)(base + blocksize * nblks), queue);
     }
 }
 
@@ -144,48 +170,63 @@ static inline void mempool_add_backtrace(FAR struct mempool_s *pool,
 int mempool_init(FAR struct mempool_s *pool, FAR const char *name)
 {
 #if CONFIG_MM_BACKTRACE >= 0
-  size_t blocksize = pool->blocksize + sizeof(struct mempool_backtrace_s);
+  size_t blocksize = ALIGN_UP(pool->blocksize +
+                              sizeof(struct mempool_backtrace_s),
+                              pool->blocksize);
 #else
   size_t blocksize = pool->blocksize;
 #endif
-  size_t ninterrupt;
-  size_t ninitial;
-  size_t count;
 
-  DEBUGASSERT(pool->blocksize != 0);
-
-  pool->nused = 0;
-  list_initialize(&pool->list);
-  list_initialize(&pool->ilist);
-  list_initialize(&pool->elist);
+  sq_init(&pool->queue);
+  sq_init(&pool->iqueue);
+  sq_init(&pool->equeue);
 
 #if CONFIG_MM_BACKTRACE >= 0
   list_initialize(&pool->alist);
+#else
+  pool->nalloc = 0;
 #endif
 
-  blocksize = ALIGN_UP(blocksize, pool->blocksize);
-  ninitial = pool->initialsize / blocksize;
-  ninterrupt = pool->interruptsize / blocksize;
-  count = ninitial + ninterrupt;
-  if (count != 0)
+  if (pool->interruptsize > sizeof(sq_entry_t))
     {
+      size_t ninterrupt = (pool->interruptsize - sizeof(sq_entry_t)) /
+                          blocksize;
+      size_t size = ninterrupt * blocksize + sizeof(sq_entry_t);
+
+      pool->ibase = mempool_malloc(pool, size);
+      if (pool->ibase == NULL)
+        {
+          return -ENOMEM;
+        }
+
+      mempool_add_queue(&pool->iqueue, pool->ibase, ninterrupt, blocksize);
+      kasan_poison(pool->ibase, size);
+    }
+  else
+    {
+      pool->ibase = NULL;
+    }
+
+  if (pool->initialsize > sizeof(sq_entry_t))
+    {
+      size_t ninitial = (pool->initialsize - sizeof(sq_entry_t)) / blocksize;
+      size_t size = ninitial * blocksize + sizeof(sq_entry_t);
       FAR char *base;
 
-      base = mempool_malloc(pool, blocksize * count +
-                            sizeof(struct list_node));
+      base = mempool_malloc(pool, size);
       if (base == NULL)
         {
+          mempool_free(pool, pool->ibase);
           return -ENOMEM;
         }
 
-      mempool_add_list(&pool->ilist, base, ninterrupt, blocksize);
-      mempool_add_list(&pool->list, base + ninterrupt * blocksize,
-                       ninitial, blocksize);
-      list_add_head(&pool->elist, (FAR struct list_node *)
-                                  (base + count * blocksize));
-      kasan_poison(base, blocksize * count);
+      mempool_add_queue(&pool->queue, base, ninitial, blocksize);
+      sq_addlast((FAR sq_entry_t *)(base + ninitial * blocksize),
+                  &pool->equeue);
+      kasan_poison(base, size);
     }
 
+  pool->lock = 0;
   if (pool->wait && pool->expandsize == 0)
     {
       nxsem_init(&pool->waitsem, 0, 0);
@@ -220,17 +261,17 @@ int mempool_init(FAR struct mempool_s *pool, FAR const char *name)
 
 FAR void *mempool_alloc(FAR struct mempool_s *pool)
 {
-  FAR struct list_node *blk;
+  FAR sq_entry_t *blk;
   irqstate_t flags;
 
 retry:
   flags = spin_lock_irqsave(&pool->lock);
-  blk = list_remove_head(&pool->list);
+  blk = mempool_remove_queue(&pool->queue);
   if (blk == NULL)
     {
       if (up_interrupt_context())
         {
-          blk = list_remove_head(&pool->ilist);
+          blk = mempool_remove_queue(&pool->iqueue);
           if (blk == NULL)
             {
               goto out_with_lock;
@@ -239,30 +280,31 @@ retry:
       else
         {
           spin_unlock_irqrestore(&pool->lock, flags);
-          if (pool->expandsize != 0)
+          if (pool->expandsize > sizeof(sq_entry_t))
             {
 #if CONFIG_MM_BACKTRACE >= 0
-              size_t blocksize = pool->blocksize +
-                                 sizeof(struct mempool_backtrace_s);
+              size_t blocksize = ALIGN_UP(pool->blocksize +
+                                 sizeof(struct mempool_backtrace_s),
+                                 pool->blocksize);
 #else
               size_t blocksize = pool->blocksize;
 #endif
-              size_t nexpand;
+              size_t nexpand = (pool->expandsize - sizeof(sq_entry_t)) /
+                               blocksize;
+              size_t size = nexpand * blocksize + sizeof(sq_entry_t);
+              FAR char *base = mempool_malloc(pool, size);
 
-              blocksize = ALIGN_UP(blocksize, pool->blocksize);
-              nexpand = pool->expandsize / blocksize;
-              blk = mempool_malloc(pool, blocksize * nexpand + sizeof(*blk));
-              if (blk == NULL)
+              if (base == NULL)
                 {
                   return NULL;
                 }
 
-              kasan_poison(blk, blocksize * nexpand);
+              kasan_poison(base, size);
               flags = spin_lock_irqsave(&pool->lock);
-              mempool_add_list(&pool->list, blk, nexpand, blocksize);
-              list_add_head(&pool->elist, (FAR struct list_node *)
-                            ((FAR char *)blk + nexpand * blocksize));
-              blk = list_remove_head(&pool->list);
+              mempool_add_queue(&pool->queue, base, nexpand, blocksize);
+              sq_addlast((FAR sq_entry_t *)(base + nexpand * blocksize),
+                         &pool->equeue);
+              blk = mempool_remove_queue(&pool->queue);
             }
           else if (!pool->wait ||
                    nxsem_wait_uninterruptible(&pool->waitsem) < 0)
@@ -276,10 +318,11 @@ retry:
         }
     }
 
-  pool->nused++;
 #if CONFIG_MM_BACKTRACE >= 0
   mempool_add_backtrace(pool, (FAR struct mempool_backtrace_s *)
                               ((FAR char *)blk + pool->blocksize));
+#else
+  pool->nalloc++;
 #endif
   kasan_unpoison(blk, pool->blocksize);
 out_with_lock:
@@ -302,44 +345,38 @@ void mempool_free(FAR struct mempool_s *pool, FAR void *blk)
 {
   irqstate_t flags;
 #if CONFIG_MM_BACKTRACE >= 0
-  size_t blocksize = pool->blocksize + sizeof(struct mempool_backtrace_s);
+  size_t blocksize =  ALIGN_UP(pool->blocksize +
+                               sizeof(struct mempool_backtrace_s),
+                               pool->blocksize);
   FAR struct mempool_backtrace_s *buf =
-  (FAR struct mempool_backtrace_s *)((FAR char *)blk + pool->blocksize);
+    (FAR struct mempool_backtrace_s *)((FAR char *)blk + pool->blocksize);
 
   list_delete(&buf->node);
 #else
   size_t blocksize = pool->blocksize;
+
+  pool->nalloc--;
 #endif
 
   flags = spin_lock_irqsave(&pool->lock);
-  if ((pool->blocksize & (pool->blocksize - 1)) == 0)
-    {
-      blocksize = ALIGN_UP(blocksize, pool->blocksize);
-    }
 
-  if (pool->interruptsize != 0)
+  if (pool->interruptsize > blocksize)
     {
-      FAR char *base;
-      size_t ninterrupt;
-
-      base = (FAR char *)(list_peek_head(&pool->elist) + 1);
-      ninterrupt = pool->interruptsize / blocksize;
-      if ((FAR char *)blk >= base &&
-          (FAR char *)blk < base + ninterrupt * blocksize)
+      if ((FAR char *)blk >= pool->ibase &&
+          (FAR char *)blk < pool->ibase + pool->interruptsize - blocksize)
         {
-          list_add_head(&pool->ilist, blk);
+          sq_addfirst(blk, &pool->iqueue);
         }
       else
         {
-          list_add_head(&pool->list, blk);
+          sq_addfirst(blk, &pool->queue);
         }
     }
   else
     {
-      list_add_head(&pool->list, blk);
+      sq_addfirst(blk, &pool->queue);
     }
 
-  pool->nused--;
   kasan_poison(blk, pool->blocksize);
   spin_unlock_irqrestore(&pool->lock, flags);
   if (pool->wait && pool->expandsize == 0)
@@ -375,10 +412,14 @@ int mempool_info(FAR struct mempool_s *pool, FAR struct mempoolinfo_s *info)
   DEBUGASSERT(pool != NULL && info != NULL);
 
   flags = spin_lock_irqsave(&pool->lock);
-  info->ordblks = list_length(&pool->list);
-  info->iordblks = list_length(&pool->ilist);
-  info->aordblks = pool->nused;
-  info->arena = (pool->nused + info->ordblks + info->iordblks) *
+  info->ordblks = mempool_queue_lenth(&pool->queue);
+  info->iordblks = mempool_queue_lenth(&pool->iqueue);
+#if CONFIG_MM_BACKTRACE >= 0
+  info->aordblks = list_length(&pool->alist);
+#else
+  info->aordblks = pool->nalloc;
+#endif
+  info->arena = (info->aordblks + info->ordblks + info->iordblks) *
                 pool->blocksize;
   spin_unlock_irqrestore(&pool->lock, flags);
   info->sizeblks = pool->blocksize;
@@ -407,7 +448,8 @@ int mempool_info_task(FAR struct mempool_s *pool,
   DEBUGASSERT(info);
   if (info->pid == -2)
     {
-      size_t count = list_length(&pool->list);
+      size_t count = mempool_queue_lenth(&pool->queue) +
+                     mempool_queue_lenth(&pool->iqueue);
 
       info->aordblks += count;
       info->uordblks += count * pool->blocksize;
@@ -415,20 +457,10 @@ int mempool_info_task(FAR struct mempool_s *pool,
   else if (info->pid == -1)
     {
 #if CONFIG_MM_BACKTRACE >= 0
-      size_t blocksize = pool->blocksize +
-             sizeof(struct mempool_backtrace_s);
+      size_t count = list_length(&pool->alist);
 #else
-      size_t blocksize = pool->blocksize;
+      size_t count = pool->nalloc;
 #endif
-      size_t count;
-
-      if ((pool->blocksize & (pool->blocksize - 1)) == 0)
-        {
-          blocksize = ALIGN_UP(blocksize, pool->blocksize);
-        }
-
-      count = (pool->initialsize + pool->interruptsize) / blocksize +
-              (list_length(&pool->elist) - 1) - list_length(&pool->list);
 
       info->aordblks += count;
       info->uordblks += count * pool->blocksize;
@@ -437,6 +469,7 @@ int mempool_info_task(FAR struct mempool_s *pool,
   else
     {
       FAR struct mempool_backtrace_s *buf;
+
       list_for_every_entry(&pool->alist, buf, struct mempool_backtrace_s,
                            node)
         {
@@ -475,18 +508,27 @@ void mempool_memdump(FAR struct mempool_s *pool, pid_t pid)
 {
   if (pid == -2)
     {
-      FAR struct list_node *node;
-      list_for_every(&pool->list, node)
+      FAR sq_entry_t *entry;
+
+      sq_for_every(&pool->queue, entry)
         {
           syslog(LOG_INFO, "%12zu%*p\n",
                  pool->blocksize, MM_PTR_FMT_WIDTH,
-                 (FAR char *)node);
+                 (FAR char *)entry);
+        }
+
+      sq_for_every(&pool->iqueue, entry)
+        {
+          syslog(LOG_INFO, "%12zu%*p\n",
+                 pool->blocksize, MM_PTR_FMT_WIDTH,
+                 (FAR char *)entry);
         }
     }
 #if CONFIG_MM_BACKTRACE >= 0
   else
     {
       FAR struct mempool_backtrace_s *buf;
+
       list_for_every_entry(&pool->alist, buf, struct mempool_backtrace_s,
                            node)
         {
@@ -529,44 +571,54 @@ void mempool_memdump(FAR struct mempool_s *pool, pid_t pid)
 int mempool_deinit(FAR struct mempool_s *pool)
 {
 #if CONFIG_MM_BACKTRACE >= 0
-  size_t blocksize = pool->blocksize + sizeof(struct mempool_backtrace_s);
+  size_t blocksize = ALIGN_UP(pool->blocksize +
+                              sizeof(struct mempool_backtrace_s),
+                              pool->blocksize);
 #else
   size_t blocksize = pool->blocksize;
 #endif
-  FAR struct list_node *blk;
-  size_t ninterrupt;
-  size_t ninitial;
-  size_t count;
+  FAR sq_entry_t *blk;
+  size_t count = 0;
 
-  if (pool->nused != 0)
+#if CONFIG_MM_BACKTRACE >= 0
+  if (!list_is_empty(&pool->alist))
+#else
+  if (pool->nalloc != 0)
+#endif
     {
       return -EBUSY;
     }
 
-#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MEMPOOL)
-  mempool_procfs_unregister(&pool->procfs);
-#endif
-
-  if ((pool->blocksize & (pool->blocksize - 1)) == 0)
+  if (pool->initialsize > sizeof(sq_entry_t))
     {
-      blocksize = ALIGN_UP(blocksize, pool->blocksize);
+      count = (pool->initialsize - sizeof(sq_entry_t)) / blocksize;
     }
 
-  ninitial = pool->initialsize / blocksize;
-  ninterrupt = pool->interruptsize / blocksize;
-  count = ninitial + ninterrupt;
   if (count == 0)
     {
-      count = pool->expandsize / blocksize;
+      if (pool->expandsize > sizeof(sq_entry_t))
+        {
+          count = (pool->expandsize - sizeof(sq_entry_t)) / blocksize;
+        }
     }
 
-  while ((blk = list_remove_head(&pool->elist)) != NULL)
+#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MEMPOOL)
+  mempool_procfs_unregister(&pool->procfs);
+#endif
+
+  while ((blk = mempool_remove_queue(&pool->equeue)) != NULL)
     {
-      blk = (FAR struct list_node *)((FAR char *)blk -
-                                     count * blocksize);
-      kasan_unpoison(blk, blocksize);
+      blk = (FAR sq_entry_t *)((FAR char *)blk - count * blocksize);
       mempool_mfree(pool, blk);
-      count = pool->expandsize / blocksize;
+      if (pool->expandsize > sizeof(sq_entry_t))
+        {
+          count = (pool->expandsize - sizeof(sq_entry_t)) / blocksize;
+        }
+    }
+
+  if (pool->ibase)
+    {
+      mempool_mfree(pool, pool->ibase);
     }
 
   if (pool->wait && pool->expandsize == 0)
diff --git a/mm/mempool/mempool_multiple.c b/mm/mempool/mempool_multiple.c
index b2233b3e24..c38c6e68ec 100644
--- a/mm/mempool/mempool_multiple.c
+++ b/mm/mempool/mempool_multiple.c
@@ -415,12 +415,9 @@ void mempool_multiple_memdump(FAR struct mempool_multiple_s *mpool,
  * Input Parameters:
  *   mpool - The handle of multiple memory pool to be used.
  *
- * Returned Value:
- *   Zero on success; A negated errno value is returned on any failure.
- *
  ****************************************************************************/
 
-int mempool_multiple_deinit(FAR struct mempool_multiple_s *mpool)
+void mempool_multiple_deinit(FAR struct mempool_multiple_s *mpool)
 {
   size_t i;
 
@@ -428,16 +425,6 @@ int mempool_multiple_deinit(FAR struct mempool_multiple_s *mpool)
 
   for (i = 0; i < mpool->npools; i++)
     {
-      if (mpool->pools[i].nused != 0)
-        {
-          return -EBUSY;
-        }
+      DEBUGVERIFY(mempool_deinit(mpool->pools + i));
     }
-
-  for (i = 0; i < mpool->npools; i++)
-    {
-      mempool_deinit(mpool->pools + i);
-    }
-
-  return 0;
 }