[RFC,10/11] malloc: allow destroying heaps
diff mbox series

Message ID 41225d71752906662b81fe939cd7fe47994133e1.1530881548.git.anatoly.burakov@intel.com
State Superseded, archived
Delegated to: Thomas Monjalon
Headers show
Series
  • Support externally allocated memory in DPDK
Related show

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Burakov, Anatoly July 6, 2018, 1:17 p.m. UTC
Add an API to destroy specified heap. Any memory regions still
contained within the heap will be removed first.

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        | 29 ++++++++++++++++++++++
 lib/librte_eal/common/malloc_heap.h        |  3 +++
 lib/librte_eal/common/rte_malloc.c         | 27 ++++++++++++++++++++
 lib/librte_eal/rte_eal_version.map         |  1 +
 5 files changed, 81 insertions(+)

Patch
diff mbox series

diff --git a/lib/librte_eal/common/include/rte_malloc.h b/lib/librte_eal/common/include/rte_malloc.h
index 25d8d3f11..239cda2ca 100644
--- a/lib/librte_eal/common/include/rte_malloc.h
+++ b/lib/librte_eal/common/include/rte_malloc.h
@@ -346,6 +346,27 @@  rte_malloc_heap_add_memory(const char *heap_name, void *va_addr, size_t len,
 int __rte_experimental
 rte_malloc_heap_remove_memory(const char *heap_name, void *va_addr, size_t len);
 
+/**
+ * Destroys a previously created malloc heap with specified name.
+ *
+ * @note Concurrently creating or destroying heaps is not thread-safe.
+ *
+ * @note This function does not deallocate the memory backing the heap - it only
+ *   deregisters memory from DPDK.
+ *
+ * @note This function will return a failure result if not all memory allocated
+ *   from the heap has been freed back to malloc heap.
+ *
+ * @param heap_name
+ *   Name of the heap to create.
+ *
+ * @return
+ *   - 0 on successful creation.
+ *   - -1 on error.
+ */
+int __rte_experimental
+rte_malloc_heap_destroy(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 27dbf6e60..e447b6412 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -1039,6 +1039,35 @@  malloc_heap_create(struct malloc_heap *heap, const char *heap_name)
 	return 0;
 }
 
+int
+malloc_heap_destroy(struct malloc_heap *heap)
+{
+	struct malloc_elem *elem;
+
+	if (heap->alloc_count != 0) {
+		RTE_LOG(ERR, EAL, "Heap is still in use\n");
+		rte_errno = EBUSY;
+		return -1;
+	}
+	elem = heap->first;
+	while (elem != NULL) {
+		struct malloc_elem *next = elem->next;
+
+		if (destroy_seg(elem, elem->size) < 0)
+			return -1;
+
+		elem = next;
+	}
+	if (heap->total_size != 0)
+		RTE_LOG(ERR, EAL, "Total size not zero, heap is likely corrupt\n");
+
+	/* we can't memset the entire thing as we're still holding the lock */
+	LIST_INIT(heap->free_head);
+	memset(&heap->name, 0, sizeof(heap->name));
+
+	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 000146365..399c9a6b1 100644
--- a/lib/librte_eal/common/malloc_heap.h
+++ b/lib/librte_eal/common/malloc_heap.h
@@ -38,6 +38,9 @@  malloc_heap_alloc_on_heap_id(const char *type, size_t size,
 int
 malloc_heap_create(struct malloc_heap *heap, const char *heap_name);
 
+int
+malloc_heap_destroy(struct malloc_heap *heap);
+
 int
 malloc_heap_add_external_memory(struct malloc_heap *heap, void *va_addr,
 		rte_iova_t iova_addrs[], unsigned int n_pages, size_t page_sz);
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index 8d2eb7250..b6beee7ce 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -385,3 +385,30 @@  rte_malloc_heap_create(const char *heap_name)
 	return malloc_heap_create(heap, heap_name);
 }
 
+int
+rte_malloc_heap_destroy(const char *heap_name)
+{
+	struct malloc_heap *heap = NULL;
+	int ret;
+
+	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;
+	}
+	/* start from non-socket heaps */
+	heap = malloc_heap_find_named_heap(heap_name);
+	if (heap == NULL) {
+		RTE_LOG(ERR, EAL, "Heap %s not found\n", heap_name);
+		rte_errno = ENOENT;
+		return -1;
+	}
+	/* sanity checks done, now we can destroy the heap */
+	rte_spinlock_lock(&heap->lock);
+	ret = malloc_heap_destroy(heap);
+	rte_spinlock_unlock(&heap->lock);
+
+	return ret;
+}
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index 7ee79051f..cdde7eb3b 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -282,6 +282,7 @@  EXPERIMENTAL {
 	rte_malloc_get_stats_from_heap;
 	rte_malloc_heap_add_memory;
 	rte_malloc_heap_create;
+	rte_malloc_heap_destroy;
 	rte_malloc_heap_remove_memory;
 	rte_mem_alloc_validator_register;
 	rte_mem_alloc_validator_unregister;