You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by je...@apache.org on 2023/01/18 08:02:41 UTC

[nuttx] 02/03: mempool:use two-dimensional array avoid competition

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

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

commit d846004533308f6b43fc0059f81e35a2fc5e32ea
Author: anjiahao <an...@xiaomi.com>
AuthorDate: Thu Dec 22 21:18:09 2022 +0800

    mempool:use two-dimensional array avoid competition
    
    Signed-off-by: anjiahao <an...@xiaomi.com>
---
 include/nuttx/mm/mempool.h    |  18 +++----
 mm/Kconfig                    |   7 +++
 mm/mempool/mempool_multiple.c | 108 +++++++++++++++++++++++++++---------------
 mm/mm_heap/mm_initialize.c    |   7 +--
 mm/tlsf/mm_tlsf.c             |   7 +--
 5 files changed, 95 insertions(+), 52 deletions(-)

diff --git a/include/nuttx/mm/mempool.h b/include/nuttx/mm/mempool.h
index 7af6558728..4c7aeaeb5c 100644
--- a/include/nuttx/mm/mempool.h
+++ b/include/nuttx/mm/mempool.h
@@ -281,13 +281,14 @@ void mempool_procfs_unregister(FAR struct mempool_procfs_entry_s *entry);
  *   relationship between the each block size of mempool in multiple mempool.
  *
  * Input Parameters:
- *   name        - The name of memory pool.
- *   poolsize    - The block size array for pools in multiples pool.
- *   npools      - How many pools in multiples pool.
- *   alloc       - The alloc memory function for multiples pool.
- *   free        - The free memory function for multiples pool.
- *   arg         - The alloc & free memory fuctions used arg.
- *   expandsize  - The expend mempry for all pools in multiples pool.
+ *   name            - The name of memory pool.
+ *   poolsize        - The block size array for pools in multiples pool.
+ *   npools          - How many pools in multiples pool.
+ *   alloc           - The alloc memory function for multiples pool.
+ *   free            - The free memory function for multiples pool.
+ *   arg             - The alloc & free memory fuctions used arg.
+ *   expandsize      - The expend mempry for all pools in multiples pool.
+ *   dict_expendsize - The expend number for multiple dictnoary
  *
  * Returned Value:
  *   Return an initialized multiple pool pointer on success,
@@ -302,7 +303,8 @@ 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);
+                      FAR void *arg, size_t expandsize,
+                      size_t dict_expendsize);
 
 /****************************************************************************
  * Name: mempool_multiple_alloc
diff --git a/mm/Kconfig b/mm/Kconfig
index 8b572f142b..5dc5c9f85d 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -196,6 +196,13 @@ 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
+	int "The expand size for multiple mempool's dictonary"
+	default MM_HEAP_MEMPOOL_EXPAND
+	depends on MM_HEAP_MEMPOOL_THRESHOLD != 0
+	---help---
+		This size describes the multiple mempool dictonary expend.
+
 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 d03b541f25..c8516ae79f 100644
--- a/mm/mempool/mempool_multiple.c
+++ b/mm/mempool/mempool_multiple.c
@@ -22,6 +22,8 @@
  * Included Files
  ****************************************************************************/
 
+#include <strings.h>
+#include <nuttx/mutex.h>
 #include <nuttx/kmalloc.h>
 #include <nuttx/mm/mempool.h>
 
@@ -73,9 +75,11 @@ struct mempool_multiple_s
    * expansion, and find the mempool by adding an index
    */
 
-  size_t                   dict_alloc;
-  size_t                   dict_used;
-  FAR struct mpool_dict_s *dict;
+  mutex_t                   dict_lock;
+  size_t                    dict_used;
+  size_t                    dict_col_num_log2;
+  size_t                    dict_row_num;
+  FAR struct mpool_dict_s **dict;
 };
 
 /****************************************************************************
@@ -133,23 +137,8 @@ static FAR void *mempool_multiple_alloc_callback(FAR struct mempool_s *pool,
 {
   FAR struct mempool_multiple_s *mpool = pool->priv;
   FAR void *ret;
-
-  if (mpool->dict_used >= mpool->dict_alloc)
-    {
-      ret = mpool->alloc(mpool->arg, sizeof(uintptr_t),
-                         mpool->dict_alloc *
-                         sizeof(struct mpool_dict_s) * 2);
-      if (ret == NULL)
-        {
-          return NULL;
-        }
-
-      memcpy(ret, mpool->dict,
-             mpool->dict_alloc * sizeof(struct mpool_dict_s));
-      mpool->free(mpool->arg, mpool->dict);
-      mpool->dict = ret;
-      mpool->dict_alloc *= 2;
-    }
+  size_t row;
+  size_t col;
 
   ret = mpool->alloc(mpool->arg, mpool->expandsize,
                      mpool->minpoolsize + size);
@@ -158,10 +147,27 @@ static FAR void *mempool_multiple_alloc_callback(FAR struct mempool_s *pool,
       return NULL;
     }
 
-  mpool->dict[mpool->dict_used].pool = pool;
-  mpool->dict[mpool->dict_used].addr = ret;
-  mpool->dict[mpool->dict_used].size = mpool->minpoolsize + size;
+  nxmutex_lock(&mpool->dict_lock);
+  row = mpool->dict_used >> mpool->dict_col_num_log2;
+
+  /* There is no new pointer address to store the dictionarys */
+
+  DEBUGASSERT(mpool->dict_row_num > row);
+
+  col = mpool->dict_used - (row << mpool->dict_col_num_log2);
+
+  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][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);
   return (FAR char *)ret + mpool->minpoolsize;
 }
 
@@ -194,6 +200,8 @@ mempool_multiple_get_dict(FAR struct mempool_multiple_s *mpool,
 {
   FAR void *addr;
   size_t index;
+  size_t row;
+  size_t col;
 
   if (mpool == NULL || blk == NULL)
     {
@@ -208,13 +216,16 @@ mempool_multiple_get_dict(FAR struct mempool_multiple_s *mpool,
       return NULL;
     }
 
-  if (mpool->dict[index].addr != addr ||
-      blk - addr >= mpool->dict[index].size)
+  row = index >> mpool->dict_col_num_log2;
+  col = index - (row << mpool->dict_col_num_log2);
+  if (mpool->dict[row] == NULL ||
+      mpool->dict[row][col].addr != addr ||
+      blk - addr >= mpool->dict[row][col].size)
     {
       return NULL;
     }
 
-  return &mpool->dict[index];
+  return &mpool->dict[row][col];
 }
 
 /****************************************************************************
@@ -235,14 +246,14 @@ mempool_multiple_get_dict(FAR struct mempool_multiple_s *mpool,
  *   relationship between the each block size of mempool in multiple mempool.
  *
  * Input Parameters:
- *   name        - The name of memory pool.
- *   poolsize    - The block size array for pools in multiples pool.
- *   npools      - How many pools in multiples pool.
- *   alloc       - The alloc memory function for multiples pool.
- *   free        - The free memory function for multiples pool.
- *   arg         - The alloc & free memory fuctions used arg.
- *   expandsize  - The expend mempry for all pools in multiples pool.
- *
+ *   name            - The name of memory pool.
+ *   poolsize        - The block size array for pools in multiples pool.
+ *   npools          - How many pools in multiples pool.
+ *   alloc           - The alloc memory function for multiples pool.
+ *   free            - The free memory function for multiples pool.
+ *   arg             - The alloc & free memory fuctions used arg.
+ *   expandsize      - The expend mempry for all pools in multiples pool.
+ *   dict_expendsize -  The expend size for multiple dictnoary
  * Returned Value:
  *   Return an initialized multiple pool pointer on success,
  *   otherwise NULL is returned.
@@ -254,7 +265,8 @@ 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)
+                      FAR void *arg, size_t expandsize,
+                      size_t dict_expendsize)
 {
   FAR struct mempool_multiple_s *mpool;
   FAR struct mempool_s *pools;
@@ -335,15 +347,22 @@ mempool_multiple_init(FAR const char *name,
         }
     }
 
-  mpool->dict_alloc = maxpoolszie / sizeof(struct mpool_dict_s) + 1;
   mpool->dict_used = 0;
-  mpool->dict = alloc(arg, sizeof(uintptr_t),
-                      mpool->dict_alloc * sizeof(struct mpool_dict_s));
+  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);
   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);
+
   return mpool;
 
 err_with_pools:
@@ -643,7 +662,20 @@ void mempool_multiple_deinit(FAR struct mempool_multiple_s *mpool)
       DEBUGVERIFY(mempool_deinit(mpool->pools + i));
     }
 
+  for (i = 0; i < mpool->dict_row_num; i++)
+    {
+      if (mpool->dict[i] != NULL)
+        {
+          mpool->free(mpool->arg, mpool->dict[i]);
+        }
+      else
+        {
+          break;
+        }
+    }
+
   mpool->free(mpool->arg, mpool->dict);
   mpool->free(mpool->arg, mpool->pools);
   mpool->free(mpool->arg, mpool);
+  nxmutex_destroy(&mpool->dict_lock);
 }
diff --git a/mm/mm_heap/mm_initialize.c b/mm/mm_heap/mm_initialize.c
index 533b5d8231..763c9387a2 100644
--- a/mm/mm_heap/mm_initialize.c
+++ b/mm/mm_heap/mm_initialize.c
@@ -256,9 +256,10 @@ 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)mm_memalign,
-                                    (mempool_multiple_free_t)mm_free, heap,
-                                    CONFIG_MM_HEAP_MEMPOOL_EXPAND);
+                                  (mempool_multiple_alloc_t)mm_memalign,
+                                  (mempool_multiple_free_t)mm_free, heap,
+                                  CONFIG_MM_HEAP_MEMPOOL_EXPAND,
+                                  CONFIG_MM_HEAP_MEMPOOL_DICTIONARY_EXPAND);
 #endif
 
   return heap;
diff --git a/mm/tlsf/mm_tlsf.c b/mm/tlsf/mm_tlsf.c
index 0bd36e20dc..308fc1ca2c 100644
--- a/mm/tlsf/mm_tlsf.c
+++ b/mm/tlsf/mm_tlsf.c
@@ -801,9 +801,10 @@ 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)mm_memalign,
-                                    (mempool_multiple_free_t)mm_free, heap,
-                                    CONFIG_MM_HEAP_MEMPOOL_EXPAND);
+                                  (mempool_multiple_alloc_t)mm_memalign,
+                                  (mempool_multiple_free_t)mm_free, heap,
+                                  CONFIG_MM_HEAP_MEMPOOL_EXPAND,
+                                  CONFIG_MM_HEAP_MEMPOOL_DICTIONARY_EXPAND);
 #endif
 
   return heap;