{
struct malloc_elem *elem = start;
- malloc_elem_init(elem, heap, msl, len);
+ malloc_elem_init(elem, heap, msl, len, elem, len);
malloc_elem_insert(elem);
if (elem->size < page_sz)
goto free_unlock;
+ /* if user requested to match allocations, the sizes must match - if not,
+ * we will defer freeing these hugepages until the entire original allocation
+ * can be freed
+ */
+ if (internal_config.match_allocations && elem->size != elem->orig_size)
+ goto free_unlock;
+
/* probably, but let's make sure, as we may not be using up full page */
start = elem;
len = elem->size;
}
static int
-destroy_seg(struct malloc_elem *elem, size_t len)
+destroy_elem(struct malloc_elem *elem, size_t len)
{
struct malloc_heap *heap = elem->heap;
- struct rte_memseg_list *msl;
-
- msl = elem->msl;
/* notify all subscribers that a memory area is going to be removed */
eal_memalloc_mem_event_notify(RTE_MEM_EVENT_FREE, elem, len);
memset(elem, 0, sizeof(*elem));
- /* destroy the fbarray backing this memory */
- if (rte_fbarray_destroy(&msl->memseg_arr) < 0)
- return -1;
-
- /* reset the memseg list */
- memset(msl, 0, sizeof(*msl));
-
return 0;
}
-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)
+struct rte_memseg_list *
+malloc_heap_create_external_seg(void *va_addr, rte_iova_t iova_addrs[],
+ unsigned int n_pages, size_t page_sz, const char *seg_name,
+ unsigned int socket_id)
{
struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
char fbarray_name[RTE_FBARRAY_NAME_LEN];
if (msl == NULL) {
RTE_LOG(ERR, EAL, "Couldn't find empty memseg list\n");
rte_errno = ENOSPC;
- return -1;
+ return NULL;
}
snprintf(fbarray_name, sizeof(fbarray_name) - 1, "%s_%p",
- heap->name, va_addr);
+ seg_name, va_addr);
/* create the backing fbarray */
if (rte_fbarray_init(&msl->memseg_arr, fbarray_name, n_pages,
sizeof(struct rte_memseg)) < 0) {
RTE_LOG(ERR, EAL, "Couldn't create fbarray backing the memseg list\n");
- return -1;
+ return NULL;
}
arr = &msl->memseg_arr;
ms->len = page_sz;
ms->nchannel = rte_memory_get_nchannel();
ms->nrank = rte_memory_get_nrank();
- ms->socket_id = heap->socket_id;
+ ms->socket_id = socket_id;
}
/* set up the memseg list */
msl->base_va = va_addr;
msl->page_sz = page_sz;
- msl->socket_id = heap->socket_id;
+ msl->socket_id = socket_id;
msl->len = seg_len;
msl->version = 0;
msl->external = 1;
+ return msl;
+}
+
+struct extseg_walk_arg {
+ void *va_addr;
+ size_t len;
+ struct rte_memseg_list *msl;
+};
+
+static int
+extseg_walk(const struct rte_memseg_list *msl, void *arg)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ struct extseg_walk_arg *wa = arg;
+
+ if (msl->base_va == wa->va_addr && msl->len == wa->len) {
+ unsigned int found_idx;
+
+ /* msl is const */
+ found_idx = msl - mcfg->memsegs;
+ wa->msl = &mcfg->memsegs[found_idx];
+ return 1;
+ }
+ return 0;
+}
+
+struct rte_memseg_list *
+malloc_heap_find_external_seg(void *va_addr, size_t len)
+{
+ struct extseg_walk_arg wa;
+ int res;
+
+ wa.va_addr = va_addr;
+ wa.len = len;
+
+ res = rte_memseg_list_walk_thread_unsafe(extseg_walk, &wa);
+
+ if (res != 1) {
+ /* 0 means nothing was found, -1 shouldn't happen */
+ if (res == 0)
+ rte_errno = ENOENT;
+ return NULL;
+ }
+ return wa.msl;
+}
+
+int
+malloc_heap_destroy_external_seg(struct rte_memseg_list *msl)
+{
+ /* destroy the fbarray backing this memory */
+ if (rte_fbarray_destroy(&msl->memseg_arr) < 0)
+ return -1;
+
+ /* reset the memseg list */
+ memset(msl, 0, sizeof(*msl));
+
+ return 0;
+}
+
+int
+malloc_heap_add_external_memory(struct malloc_heap *heap,
+ struct rte_memseg_list *msl)
+{
/* erase contents of new memory */
- memset(va_addr, 0, seg_len);
+ memset(msl->base_va, 0, msl->len);
/* now, add newly minted memory to the malloc heap */
- malloc_heap_add_memory(heap, msl, va_addr, seg_len);
+ malloc_heap_add_memory(heap, msl, msl->base_va, msl->len);
- heap->total_size += seg_len;
+ heap->total_size += msl->len;
/* all done! */
RTE_LOG(DEBUG, EAL, "Added segment for heap %s starting at %p\n",
- heap->name, va_addr);
+ heap->name, msl->base_va);
/* notify all subscribers that a new memory area has been added */
eal_memalloc_mem_event_notify(RTE_MEM_EVENT_ALLOC,
- va_addr, seg_len);
+ msl->base_va, msl->len);
return 0;
}
rte_errno = EBUSY;
return -1;
}
- return destroy_seg(elem, len);
+ return destroy_elem(elem, len);
}
int
struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
unsigned int i;
+ if (internal_config.match_allocations) {
+ RTE_LOG(DEBUG, EAL, "Hugepages will be freed exactly as allocated.\n");
+ }
+
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
/* assign min socket ID to external heaps */
mcfg->next_socket_id = EXTERNAL_HEAP_MIN_SOCKET_ID;