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.burakov@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(+)
@@ -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.
@@ -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)
{
@@ -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);
@@ -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);
+}
+
@@ -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;