Add API to allow creating new malloc heaps. They will be created
with indexes higher than heaps reserved for NUMA sockets, and up to
RTE_MAX_HEAPS.

Signed-off-by: Anatoly Burakov <anatoly.bura...@intel.com>
---
 lib/librte_eal/common/include/rte_malloc.h | 21 ++++++++++
 lib/librte_eal/common/malloc_heap.c        | 16 ++++++++
 lib/librte_eal/common/malloc_heap.h        |  3 ++
 lib/librte_eal/common/rte_malloc.c         | 46 ++++++++++++++++++++++
 lib/librte_eal/rte_eal_version.map         |  1 +
 5 files changed, 87 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_malloc.h 
b/lib/librte_eal/common/include/rte_malloc.h
index f1bcd9b65..fa6de073a 100644
--- a/lib/librte_eal/common/include/rte_malloc.h
+++ b/lib/librte_eal/common/include/rte_malloc.h
@@ -253,6 +253,27 @@ rte_malloc_from_heap(const char *heap_name, const char 
*type, size_t size,
 void
 rte_free(void *ptr);
 
+/**
+ * Creates a new empty malloc heap with a specified name.
+ *
+ * @note Concurrently creating or destroying heaps is not safe.
+ *
+ * @note This function does not need to be called in multiple processes, as
+ *   multiprocess synchronization will happen automatically as far as heap data
+ *   is concerned. However, before accessing pointers to memory in this heap, 
it
+ *   is responsibility of the user to ensure that the heap memory is accessible
+ *   in all processes.
+ *
+ * @param heap_name
+ *   Name of the heap to create.
+ *
+ * @return
+ *   - 0 on successful creation.
+ *   - -1 on error.
+ */
+int __rte_experimental
+rte_malloc_heap_create(const char *heap_name);
+
 /**
  * If malloc debug is enabled, check a memory block for header
  * and trailer markers to indicate that all is well with the block.
diff --git a/lib/librte_eal/common/malloc_heap.c 
b/lib/librte_eal/common/malloc_heap.c
index a33acc252..f5d103626 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -892,6 +892,22 @@ malloc_heap_dump(struct malloc_heap *heap, FILE *f)
        rte_spinlock_unlock(&heap->lock);
 }
 
+int
+malloc_heap_create(struct malloc_heap *heap, const char *heap_name)
+{
+       /* initialize empty heap */
+       heap->alloc_count = 0;
+       heap->first = NULL;
+       heap->last = NULL;
+       LIST_INIT(heap->free_head);
+       rte_spinlock_init(&heap->lock);
+       heap->total_size = 0;
+
+       /* set up name */
+       strlcpy(heap->name, heap_name, RTE_HEAP_NAME_MAX_LEN);
+       return 0;
+}
+
 int
 rte_eal_malloc_heap_init(void)
 {
diff --git a/lib/librte_eal/common/malloc_heap.h 
b/lib/librte_eal/common/malloc_heap.h
index a7e408c99..aa819ef65 100644
--- a/lib/librte_eal/common/malloc_heap.h
+++ b/lib/librte_eal/common/malloc_heap.h
@@ -35,6 +35,9 @@ malloc_heap_alloc_on_heap_id(const char *type, size_t size,
                unsigned int heap_id, unsigned int flags, size_t align,
                size_t bound, bool contig);
 
+int
+malloc_heap_create(struct malloc_heap *heap, const char *heap_name);
+
 int
 malloc_heap_find_named_heap_idx(const char *name);
 
diff --git a/lib/librte_eal/common/rte_malloc.c 
b/lib/librte_eal/common/rte_malloc.c
index 215876a59..e000dc5b7 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -12,6 +12,7 @@
 #include <rte_memory.h>
 #include <rte_eal.h>
 #include <rte_eal_memconfig.h>
+#include <rte_errno.h>
 #include <rte_branch_prediction.h>
 #include <rte_debug.h>
 #include <rte_launch.h>
@@ -272,3 +273,48 @@ rte_malloc_virt2iova(const void *addr)
 
        return ms->iova + RTE_PTR_DIFF(addr, ms->addr);
 }
+
+int
+rte_malloc_heap_create(const char *heap_name)
+{
+       struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+       struct malloc_heap *heap = NULL;
+       int i;
+
+       /* iova_addrs is allowed to be NULL */
+       if (heap_name == NULL ||
+                       strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) == 0 ||
+                       strnlen(heap_name, RTE_HEAP_NAME_MAX_LEN) ==
+                               RTE_HEAP_NAME_MAX_LEN) {
+               rte_errno = EINVAL;
+               return -1;
+       }
+       /* check if there is space in the heap list, or if heap with this name
+        * already exists. start from non-socket heaps.
+        */
+       for (i = rte_socket_count(); i < RTE_MAX_HEAPS; i++) {
+               struct malloc_heap *tmp = &mcfg->malloc_heaps[i];
+               /* existing heap */
+               if (strncmp(heap_name, tmp->name,
+                               RTE_HEAP_NAME_MAX_LEN) == 0) {
+                       RTE_LOG(ERR, EAL, "Heap %s already exists\n",
+                               heap_name);
+                       rte_errno = EEXIST;
+                       return -1;
+               }
+               /* empty heap */
+               if (strnlen(tmp->name, RTE_HEAP_NAME_MAX_LEN) == 0) {
+                       heap = tmp;
+                       break;
+               }
+       }
+       if (heap == NULL) {
+               RTE_LOG(ERR, EAL, "Cannot create new heap: no space\n");
+               rte_errno = ENOSPC;
+               return -1;
+       }
+
+       /* we're sure that we can create a new heap, so do it */
+       return malloc_heap_create(heap, heap_name);
+}
+
diff --git a/lib/librte_eal/rte_eal_version.map 
b/lib/librte_eal/rte_eal_version.map
index 716a7585d..f3c375156 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -280,6 +280,7 @@ EXPERIMENTAL {
        rte_malloc_dump_heaps;
        rte_malloc_from_heap;
        rte_malloc_get_stats_from_heap;
+       rte_malloc_heap_create;
        rte_mem_alloc_validator_register;
        rte_mem_alloc_validator_unregister;
        rte_mem_event_callback_register;
-- 
2.17.1

Reply via email to