malloc: allow destroying heaps
authorAnatoly Burakov <anatoly.burakov@intel.com>
Tue, 2 Oct 2018 13:34:50 +0000 (14:34 +0100)
committerThomas Monjalon <thomas@monjalon.net>
Thu, 11 Oct 2018 09:56:55 +0000 (11:56 +0200)
Add an API to destroy specified heap.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
lib/librte_eal/common/include/rte_malloc.h
lib/librte_eal/common/malloc_heap.c
lib/librte_eal/common/malloc_heap.h
lib/librte_eal/common/rte_malloc.c
lib/librte_eal/rte_eal_version.map

index e326529..309bbbc 100644 (file)
@@ -282,6 +282,29 @@ rte_malloc_get_socket_stats(int socket,
 int __rte_experimental
 rte_malloc_heap_create(const char *heap_name);
 
+/**
+ * Destroys a previously created malloc heap with specified name.
+ *
+ * @note This function will return a failure result if not all memory allocated
+ *   from the heap has been freed back to the heap
+ *
+ * @note This function will return a failure result if not all memory segments
+ *   were removed from the heap prior to its destruction
+ *
+ * @param heap_name
+ *   Name of the heap to create.
+ *
+ * @return
+ *   - 0 on success
+ *   - -1 in case of error, with rte_errno set to one of the following:
+ *     EINVAL - ``heap_name`` was NULL, empty or too long
+ *     ENOENT - heap by the name of ``heap_name`` was not found
+ *     EPERM  - attempting to destroy reserved heap
+ *     EBUSY  - heap still contains data
+ */
+int __rte_experimental
+rte_malloc_heap_destroy(const char *heap_name);
+
 /**
  * Find socket ID corresponding to a named heap.
  *
index 00fdf54..ca774c9 100644 (file)
@@ -1053,6 +1053,28 @@ malloc_heap_create(struct malloc_heap *heap, const char *heap_name)
        return 0;
 }
 
+int
+malloc_heap_destroy(struct malloc_heap *heap)
+{
+       if (heap->alloc_count != 0) {
+               RTE_LOG(ERR, EAL, "Heap is still in use\n");
+               rte_errno = EBUSY;
+               return -1;
+       }
+       if (heap->first != NULL || heap->last != NULL) {
+               RTE_LOG(ERR, EAL, "Heap still contains memory segments\n");
+               rte_errno = EBUSY;
+               return -1;
+       }
+       if (heap->total_size != 0)
+               RTE_LOG(ERR, EAL, "Total size not zero, heap is likely corrupt\n");
+
+       /* after this, the lock will be dropped */
+       memset(heap, 0, sizeof(*heap));
+
+       return 0;
+}
+
 int
 rte_eal_malloc_heap_init(void)
 {
index eebee16..75278da 100644 (file)
@@ -36,6 +36,9 @@ malloc_heap_alloc_biggest(const char *type, int socket, unsigned int flags,
 int
 malloc_heap_create(struct malloc_heap *heap, const char *heap_name);
 
+int
+malloc_heap_destroy(struct malloc_heap *heap);
+
 int
 malloc_heap_free(struct malloc_elem *elem);
 
index c6cb0a8..23537bc 100644 (file)
@@ -312,6 +312,21 @@ rte_malloc_virt2iova(const void *addr)
        return ms->iova + RTE_PTR_DIFF(addr, ms->addr);
 }
 
+static struct malloc_heap *
+find_named_heap(const char *name)
+{
+       struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+       unsigned int i;
+
+       for (i = 0; i < RTE_MAX_HEAPS; i++) {
+               struct malloc_heap *heap = &mcfg->malloc_heaps[i];
+
+               if (!strncmp(name, heap->name, RTE_HEAP_NAME_MAX_LEN))
+                       return heap;
+       }
+       return NULL;
+}
+
 int
 rte_malloc_heap_create(const char *heap_name)
 {
@@ -362,3 +377,46 @@ unlock:
 
        return ret;
 }
+
+int
+rte_malloc_heap_destroy(const char *heap_name)
+{
+       struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+       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;
+       }
+       rte_rwlock_write_lock(&mcfg->memory_hotplug_lock);
+
+       /* start from non-socket heaps */
+       heap = find_named_heap(heap_name);
+       if (heap == NULL) {
+               RTE_LOG(ERR, EAL, "Heap %s not found\n", heap_name);
+               rte_errno = ENOENT;
+               ret = -1;
+               goto unlock;
+       }
+       /* we shouldn't be able to destroy internal heaps */
+       if (heap->socket_id < RTE_MAX_NUMA_NODES) {
+               rte_errno = EPERM;
+               ret = -1;
+               goto unlock;
+       }
+       /* sanity checks done, now we can destroy the heap */
+       rte_spinlock_lock(&heap->lock);
+       ret = malloc_heap_destroy(heap);
+
+       /* if we failed, lock is still active */
+       if (ret < 0)
+               rte_spinlock_unlock(&heap->lock);
+unlock:
+       rte_rwlock_write_unlock(&mcfg->memory_hotplug_lock);
+
+       return ret;
+}
index 376f33b..27aac5b 100644 (file)
@@ -319,6 +319,7 @@ EXPERIMENTAL {
        rte_log_register_type_and_pick_level;
        rte_malloc_dump_heaps;
        rte_malloc_heap_create;
+       rte_malloc_heap_destroy;
        rte_malloc_heap_get_socket;
        rte_malloc_heap_socket_is_external;
        rte_mem_alloc_validator_register;