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