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 6572081e075f2b20faa56463a78f7e469faafced
Author: anjiahao <[email protected]>
AuthorDate: Fri May 26 10:42:50 2023 +0800

    mempool:Allocate a chunk for multiple mempool avoid memory fragmentation
    
    Signed-off-by: anjiahao <[email protected]>
---
 include/nuttx/mm/mempool.h    |   5 +-
 mm/Kconfig                    |  13 +++-
 mm/mempool/mempool_multiple.c | 151 ++++++++++++++++++++++++++++++++++--------
 mm/mm_heap/mm_initialize.c    |   9 +--
 mm/tlsf/mm_tlsf.c             |   9 +--
 5 files changed, 146 insertions(+), 41 deletions(-)

diff --git a/include/nuttx/mm/mempool.h b/include/nuttx/mm/mempool.h
index 22de090de7..875f2f41c0 100644
--- a/include/nuttx/mm/mempool.h
+++ b/include/nuttx/mm/mempool.h
@@ -322,6 +322,7 @@ void mempool_procfs_unregister(FAR struct 
mempool_procfs_entry_s *entry);
  *   alloc           - The alloc memory function for multiples pool.
  *   free            - The free memory function for multiples pool.
  *   arg             - The alloc & free memory fuctions used arg.
+ *   chunksize       - The multiples pool chunk size.
  *   expandsize      - The expend mempry for all pools in multiples pool.
  *   dict_expendsize - The expend size for multiple dictnoary.
  * Returned Value:
@@ -336,8 +337,8 @@ FAR struct mempool_multiple_s *
 mempool_multiple_init(FAR const char *name,
                       FAR size_t *poolsize, size_t npools,
                       mempool_multiple_alloc_t alloc,
-                      mempool_multiple_free_t free,
-                      FAR void *arg, size_t expandsize,
+                      mempool_multiple_free_t free, FAR void *arg,
+                      size_t chunksize, size_t expandsize,
                       size_t dict_expendsize);
 
 /****************************************************************************
diff --git a/mm/Kconfig b/mm/Kconfig
index 561ba7ed10..be3954b153 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -207,7 +207,7 @@ config MM_HEAP_MEMPOOL_THRESHOLD
                than the threshold, the memory will be requested from the
                multiple mempool by default.
 
-config MM_HEAP_MEMPOOL_EXPAND
+config MM_HEAP_MEMPOOL_EXPAND_SIZE
        int "The expand size for each mempool in multiple mempool"
        default 4096
        depends on MM_HEAP_MEMPOOL_THRESHOLD != 0
@@ -215,13 +215,20 @@ config MM_HEAP_MEMPOOL_EXPAND
                This size describes the size of each expansion of each memory
                pool with insufficient memory in the multi-level memory pool.
 
-config MM_HEAP_MEMPOOL_DICTIONARY_EXPAND
+config MM_HEAP_MEMPOOL_DICTIONARY_EXPAND_SIZE
        int "The expand size for multiple mempool's dictonary"
-       default MM_HEAP_MEMPOOL_EXPAND
+       default MM_HEAP_MEMPOOL_EXPAND_SIZE
        depends on MM_HEAP_MEMPOOL_THRESHOLD != 0
        ---help---
                This size describes the multiple mempool dictonary expend.
 
+config MM_HEAP_MEMPOOL_CHUNK_SIZE
+       int "The multiples pool chunk size"
+       default 0
+       depends on MM_HEAP_MEMPOOL_THRESHOLD != 0
+       ---help---
+               This size describes the multiple mempool chunk size.
+
 config FS_PROCFS_EXCLUDE_MEMPOOL
        bool "Exclude mempool"
        default DEFAULT_SMALL
diff --git a/mm/mempool/mempool_multiple.c b/mm/mempool/mempool_multiple.c
index 9c42c630c3..273bcc4880 100644
--- a/mm/mempool/mempool_multiple.c
+++ b/mm/mempool/mempool_multiple.c
@@ -52,6 +52,15 @@ struct mpool_dict_s
   size_t                size; /* Record expand memary size */
 };
 
+struct mpool_chunk_s
+{
+  sq_entry_t entry;
+  FAR void *start;
+  FAR void *next;
+  FAR void *end;
+  size_t used;
+};
+
 struct mempool_multiple_s
 {
   FAR struct mempool_s    *pools;       /* The memory pool array */
@@ -79,7 +88,9 @@ struct mempool_multiple_s
    * expansion, and find the mempool by adding an index
    */
 
-  mutex_t                   dict_lock;
+  mutex_t                   lock;
+  sq_queue_t                chunk_queue;
+  size_t                    chunk_size;
   size_t                    dict_used;
   size_t                    dict_col_num_log2;
   size_t                    dict_row_num;
@@ -136,6 +147,83 @@ mempool_multiple_find(FAR struct mempool_multiple_s 
*mpool, size_t size)
   return &mpool->pools[left];
 }
 
+static FAR void *
+mempool_multiple_alloc_chunk(FAR struct mempool_multiple_s *mpool,
+                             size_t align, size_t size)
+{
+  FAR struct mpool_chunk_s *chunk;
+  FAR char *tmp;
+  FAR void *ret;
+
+  if (mpool->chunk_size < mpool->expandsize)
+    {
+      return mpool->alloc(mpool->arg, align, size);
+    }
+
+  chunk = (FAR struct mpool_chunk_s *)sq_peek(&mpool->chunk_queue);
+  if (chunk == NULL)
+    {
+retry:
+      tmp = mpool->alloc(mpool->arg, mpool->expandsize,
+                         mpool->chunk_size +
+                         sizeof(struct mpool_chunk_s));
+
+      if (tmp == NULL)
+        {
+          return NULL;
+        }
+
+      chunk = (FAR struct mpool_chunk_s *)(tmp + mpool->chunk_size);
+      chunk->end = tmp + mpool->chunk_size;
+      chunk->start = tmp;
+      chunk->next = tmp;
+      chunk->used = 0;
+      sq_addfirst(&chunk->entry, &mpool->chunk_queue);
+    }
+
+  ret = (FAR void *)ALIGN_UP(chunk->next, align);
+  if (chunk->end - ret < size)
+    {
+      goto retry;
+    }
+
+  chunk->used++;
+  chunk->next = ret + size;
+  return ret;
+}
+
+static void
+mempool_multiple_free_chunk(FAR struct mempool_multiple_s *mpool,
+                            FAR void *ptr)
+{
+  FAR struct mpool_chunk_s *chunk;
+  FAR sq_entry_t *entry;
+
+  if (mpool->chunk_size < mpool->expandsize)
+    {
+      mpool->free(mpool->arg, ptr);
+      return;
+    }
+
+  nxmutex_lock(&mpool->lock);
+  sq_for_every(&mpool->chunk_queue, entry)
+    {
+      chunk = (FAR struct mpool_chunk_s *)entry;
+      if (ptr >= chunk->start && ptr < chunk->next)
+        {
+          if (--chunk->used == 0)
+            {
+              sq_rem(&chunk->entry, &mpool->chunk_queue);
+              mpool->free(mpool->arg, chunk->start);
+            }
+
+          break;
+        }
+    }
+
+  nxmutex_unlock(&mpool->lock);
+}
+
 static FAR void *mempool_multiple_alloc_callback(FAR struct mempool_s *pool,
                                                  size_t size)
 {
@@ -144,14 +232,15 @@ static FAR void *mempool_multiple_alloc_callback(FAR 
struct mempool_s *pool,
   size_t row;
   size_t col;
 
-  ret = mpool->alloc(mpool->arg, mpool->expandsize,
-                     mpool->minpoolsize + size);
+  nxmutex_lock(&mpool->lock);
+  ret = mempool_multiple_alloc_chunk(mpool, mpool->expandsize,
+                                     mpool->minpoolsize + size);
   if (ret == NULL)
     {
+      nxmutex_unlock(&mpool->lock);
       return NULL;
     }
 
-  nxmutex_lock(&mpool->dict_lock);
   row = mpool->dict_used >> mpool->dict_col_num_log2;
 
   /* There is no new pointer address to store the dictionarys */
@@ -162,16 +251,17 @@ static FAR void *mempool_multiple_alloc_callback(FAR 
struct mempool_s *pool,
 
   if (mpool->dict[row] == NULL)
     {
-      mpool->dict[row] = mpool->alloc(mpool->arg, sizeof(uintptr_t),
-                                      (1 << mpool->dict_col_num_log2) *
-                                      sizeof(struct mpool_dict_s));
+      mpool->dict[row] =
+        mempool_multiple_alloc_chunk(mpool, sizeof(uintptr_t),
+                                     (1 << mpool->dict_col_num_log2)
+                                     * sizeof(struct mpool_dict_s));
     }
 
   mpool->dict[row][col].pool = pool;
   mpool->dict[row][col].addr = ret;
   mpool->dict[row][col].size = mpool->minpoolsize + size;
   *(FAR size_t *)ret = mpool->dict_used++;
-  nxmutex_unlock(&mpool->dict_lock);
+  nxmutex_unlock(&mpool->lock);
   return (FAR char *)ret + mpool->minpoolsize;
 }
 
@@ -180,7 +270,8 @@ static void mempool_multiple_free_callback(FAR struct 
mempool_s *pool,
 {
   FAR struct mempool_multiple_s *mpool = pool->priv;
 
-  mpool->free(mpool->arg, (FAR char *)addr - mpool->minpoolsize);
+  mempool_multiple_free_chunk(mpool,
+                              (FAR char *)addr - mpool->minpoolsize);
 }
 
 /****************************************************************************
@@ -256,6 +347,7 @@ mempool_multiple_get_dict(FAR struct mempool_multiple_s 
*mpool,
  *   alloc           - The alloc memory function for multiples pool.
  *   free            - The free memory function for multiples pool.
  *   arg             - The alloc & free memory fuctions used arg.
+ *   chunksize       - The multiples pool chunk size.
  *   expandsize      - The expend mempry for all pools in multiples pool.
  *   dict_expendsize - The expend size for multiple dictnoary.
  * Returned Value:
@@ -268,8 +360,8 @@ FAR struct mempool_multiple_s *
 mempool_multiple_init(FAR const char *name,
                       FAR size_t *poolsize, size_t npools,
                       mempool_multiple_alloc_t alloc,
-                      mempool_multiple_free_t free,
-                      FAR void *arg, size_t expandsize,
+                      mempool_multiple_free_t free, FAR void *arg,
+                      size_t chunksize, size_t expandsize,
                       size_t dict_expendsize)
 {
   FAR struct mempool_multiple_s *mpool;
@@ -305,8 +397,14 @@ mempool_multiple_init(FAR const char *name,
       return NULL;
     }
 
-  pools = alloc(arg, sizeof(uintptr_t),
-                npools * sizeof(FAR struct mempool_s));
+  mpool->expandsize = expandsize;
+  mpool->chunk_size = chunksize;
+  mpool->alloc = alloc;
+  mpool->free = free;
+  mpool->arg = arg;
+  sq_init(&mpool->chunk_queue);
+  pools = mempool_multiple_alloc_chunk(mpool, sizeof(uintptr_t),
+                                       npools * sizeof(struct mempool_s));
   if (pools == NULL)
     {
       goto err_with_mpool;
@@ -314,11 +412,7 @@ mempool_multiple_init(FAR const char *name,
 
   mpool->pools = pools;
   mpool->npools = npools;
-  mpool->expandsize = expandsize;
   mpool->minpoolsize = minpoolsize;
-  mpool->alloc = alloc;
-  mpool->free = free;
-  mpool->arg = arg;
   mpool->delta = 0;
 
   for (i = 0; i < npools; i++)
@@ -358,17 +452,18 @@ mempool_multiple_init(FAR const char *name,
   mpool->dict_col_num_log2 = fls(dict_expendsize /
                                  sizeof(struct mpool_dict_s));
 
-  mpool->dict_row_num = dict_expendsize / sizeof(struct mpool_dict_s *);
-  mpool->dict = alloc(arg, sizeof(struct mpool_dict_s *),
-                      sizeof(struct mpool_dict_s *) * mpool->dict_row_num);
+  mpool->dict_row_num = dict_expendsize / sizeof(FAR struct mpool_dict_s *);
+  mpool->dict = mempool_multiple_alloc_chunk(
+                mpool, sizeof(FAR struct mpool_dict_s *),
+                sizeof(FAR struct mpool_dict_s *) * mpool->dict_row_num);
   if (mpool->dict == NULL)
     {
       goto err_with_pools;
     }
 
   memset(mpool->dict, 0,
-         mpool->dict_row_num * sizeof(struct mpool_dict_s *));
-  nxmutex_init(&mpool->dict_lock);
+         mpool->dict_row_num * sizeof(FAR struct mpool_dict_s *));
+  nxmutex_init(&mpool->lock);
 
   return mpool;
 
@@ -378,7 +473,7 @@ err_with_pools:
       mempool_deinit(pools + i);
     }
 
-  free(arg, pools);
+  mempool_multiple_free_chunk(mpool, pools);
 err_with_mpool:
   free(arg, mpool);
   return NULL;
@@ -687,7 +782,7 @@ void mempool_multiple_deinit(FAR struct mempool_multiple_s 
*mpool)
     {
       if (mpool->dict[i] != NULL)
         {
-          mpool->free(mpool->arg, mpool->dict[i]);
+          mempool_multiple_free_chunk(mpool, mpool->dict[i]);
         }
       else
         {
@@ -695,8 +790,8 @@ void mempool_multiple_deinit(FAR struct mempool_multiple_s 
*mpool)
         }
     }
 
-  mpool->free(mpool->arg, mpool->dict);
-  mpool->free(mpool->arg, mpool->pools);
-  mpool->free(mpool->arg, mpool);
-  nxmutex_destroy(&mpool->dict_lock);
+  mempool_multiple_free_chunk(mpool, mpool->dict);
+  mempool_multiple_free_chunk(mpool, mpool->pools);
+  nxmutex_destroy(&mpool->lock);
+  mpool->free(mpool, mpool);
 }
diff --git a/mm/mm_heap/mm_initialize.c b/mm/mm_heap/mm_initialize.c
index 3135f55e1c..44dc34219c 100644
--- a/mm/mm_heap/mm_initialize.c
+++ b/mm/mm_heap/mm_initialize.c
@@ -287,10 +287,11 @@ FAR struct mm_heap_s *mm_initialize(FAR const char *name,
     }
 
   heap->mm_mpool = mempool_multiple_init(name, poolsize, MEMPOOL_NPOOLS,
-                                  (mempool_multiple_alloc_t)mempool_memalign,
-                                  (mempool_multiple_free_t)mm_free, heap,
-                                  CONFIG_MM_HEAP_MEMPOOL_EXPAND,
-                                  CONFIG_MM_HEAP_MEMPOOL_DICTIONARY_EXPAND);
+                              (mempool_multiple_alloc_t)mempool_memalign,
+                              (mempool_multiple_free_t)mm_free, heap,
+                              CONFIG_MM_HEAP_MEMPOOL_CHUNK_SIZE,
+                              CONFIG_MM_HEAP_MEMPOOL_EXPAND_SIZE,
+                              CONFIG_MM_HEAP_MEMPOOL_DICTIONARY_EXPAND_SIZE);
 #endif
 
   return heap;
diff --git a/mm/tlsf/mm_tlsf.c b/mm/tlsf/mm_tlsf.c
index 0fceb7ccee..7ecd8d9ce6 100644
--- a/mm/tlsf/mm_tlsf.c
+++ b/mm/tlsf/mm_tlsf.c
@@ -844,10 +844,11 @@ FAR struct mm_heap_s *mm_initialize(FAR const char *name,
     }
 
   heap->mm_mpool = mempool_multiple_init(name, poolsize, MEMPOOL_NPOOLS,
-                                  (mempool_multiple_alloc_t)mempool_memalign,
-                                  (mempool_multiple_free_t)mm_free, heap,
-                                  CONFIG_MM_HEAP_MEMPOOL_EXPAND,
-                                  CONFIG_MM_HEAP_MEMPOOL_DICTIONARY_EXPAND);
+                              (mempool_multiple_alloc_t)mempool_memalign,
+                              (mempool_multiple_free_t)mm_free, heap,
+                              CONFIG_MM_HEAP_MEMPOOL_CHUNK_SIZE,
+                              CONFIG_MM_HEAP_MEMPOOL_EXPAND_SIZE,
+                              CONFIG_MM_HEAP_MEMPOOL_DICTIONARY_EXPAND_SIZE);
 #endif
 
   return heap;

Reply via email to