/* * Resize allocated memory. */ void * rte_realloc(void *ptr, size_t size, unsigned align) { if (ptr == NULL) return rte_malloc(NULL, size, align); struct malloc_elem *elem = malloc_elem_from_data(ptr); if (elem == NULL) rte_panic("Fatal error: memory corruption detected\n"); size = CACHE_LINE_ROUNDUP(size), align = CACHE_LINE_ROUNDUP(align); /* check alignment matches first, and if ok, see if we can resize block */ if (RTE_PTR_ALIGN(ptr,align) == ptr && malloc_elem_resize(elem, size) == 0) return ptr; /* either alignment is off, or we have no room to expand, * so move data. */ void *new_ptr = rte_malloc(NULL, size, align); if (new_ptr == NULL) return NULL; const unsigned old_size = elem->size - MALLOC_ELEM_OVERHEAD; rte_memcpy(new_ptr, ptr, old_size < size ? old_size : size); rte_free(ptr); return new_ptr; }
/* * Return the physical address of a virtual address obtained through rte_malloc */ phys_addr_t rte_malloc_virt2phy(const void *addr) { const struct malloc_elem *elem = malloc_elem_from_data(addr); if (elem == NULL) return 0; return elem->mz->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->mz->addr); }
int rte_malloc_validate(const void *ptr, size_t *size) { const struct malloc_elem *elem = malloc_elem_from_data(ptr); if (!malloc_elem_cookies_ok(elem)) return -1; if (size != NULL) *size = elem->size - elem->pad - MALLOC_ELEM_OVERHEAD; return 0; }
static const struct rte_memzone * memzone_reserve_aligned_thread_unsafe(const char *name, size_t len, int socket_id, unsigned flags, unsigned align, unsigned bound) { struct rte_memzone *mz; struct rte_mem_config *mcfg; size_t requested_len; int socket, i; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; /* no more room in config */ if (mcfg->memzone_cnt >= RTE_MAX_MEMZONE) { RTE_LOG(ERR, EAL, "%s(): No more room in config\n", __func__); rte_errno = ENOSPC; return NULL; } /* zone already exist */ if ((memzone_lookup_thread_unsafe(name)) != NULL) { RTE_LOG(DEBUG, EAL, "%s(): memzone <%s> already exists\n", __func__, name); rte_errno = EEXIST; return NULL; } if (strlen(name) >= sizeof(mz->name) - 1) { RTE_LOG(DEBUG, EAL, "%s(): memzone <%s>: name too long\n", __func__, name); rte_errno = EEXIST; return NULL; } /* if alignment is not a power of two */ if (align && !rte_is_power_of_2(align)) { RTE_LOG(ERR, EAL, "%s(): Invalid alignment: %u\n", __func__, align); rte_errno = EINVAL; return NULL; } /* alignment less than cache size is not allowed */ if (align < RTE_CACHE_LINE_SIZE) align = RTE_CACHE_LINE_SIZE; /* align length on cache boundary. Check for overflow before doing so */ if (len > SIZE_MAX - RTE_CACHE_LINE_MASK) { rte_errno = EINVAL; /* requested size too big */ return NULL; } len += RTE_CACHE_LINE_MASK; len &= ~((size_t) RTE_CACHE_LINE_MASK); /* save minimal requested length */ requested_len = RTE_MAX((size_t)RTE_CACHE_LINE_SIZE, len); /* check that boundary condition is valid */ if (bound != 0 && (requested_len > bound || !rte_is_power_of_2(bound))) { rte_errno = EINVAL; return NULL; } if ((socket_id != SOCKET_ID_ANY) && (socket_id >= RTE_MAX_NUMA_NODES)) { rte_errno = EINVAL; return NULL; } if (!rte_eal_has_hugepages()) socket_id = SOCKET_ID_ANY; if (len == 0) { if (bound != 0) requested_len = bound; else { requested_len = find_heap_max_free_elem(&socket_id, align); if (requested_len == 0) { rte_errno = ENOMEM; return NULL; } } } if (socket_id == SOCKET_ID_ANY) socket = malloc_get_numa_socket(); else socket = socket_id; /* allocate memory on heap */ void *mz_addr = malloc_heap_alloc(&mcfg->malloc_heaps[socket], NULL, requested_len, flags, align, bound); if ((mz_addr == NULL) && (socket_id == SOCKET_ID_ANY)) { /* try other heaps */ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) { if (socket == i) continue; mz_addr = malloc_heap_alloc(&mcfg->malloc_heaps[i], NULL, requested_len, flags, align, bound); if (mz_addr != NULL) break; } } if (mz_addr == NULL) { rte_errno = ENOMEM; return NULL; } const struct malloc_elem *elem = malloc_elem_from_data(mz_addr); /* fill the zone in config */ mz = get_next_free_memzone(); if (mz == NULL) { RTE_LOG(ERR, EAL, "%s(): Cannot find free memzone but there is room " "in config!\n", __func__); rte_errno = ENOSPC; return NULL; } mcfg->memzone_cnt++; snprintf(mz->name, sizeof(mz->name), "%s", name); mz->phys_addr = rte_malloc_virt2phy(mz_addr); mz->addr = mz_addr; mz->len = (requested_len == 0 ? elem->size : requested_len); mz->hugepage_sz = elem->ms->hugepage_sz; mz->socket_id = elem->ms->socket_id; mz->flags = 0; mz->memseg_id = elem->ms - rte_eal_get_configuration()->mem_config->memseg; return mz; }
/* Free the memory space back to heap */ void rte_free(void *addr) { if (addr == NULL) return; if (malloc_elem_free(malloc_elem_from_data(addr)) < 0) rte_panic("Fatal error: Invalid memory\n"); }