mem: introduce memzone freeing
Implement rte_memzone_free which, as its name implies, would free a memzone. Currently memzone are tracked in an array and cannot be free. To be able to reuse the same array to track memzones, we have to change how we keep track of reserved memzones. With this patch, any memzone with addr NULL is not used, so we also need to change how we look for the next memzone entry free. Add new unit test for rte_memzone_free API. Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
This commit is contained in:
parent
89f3a81574
commit
ff909fe21f
@ -432,7 +432,6 @@ test_memzone_reserve_max(void)
|
||||
printf("Expected size = %zu, actual size = %zu\n", maxlen, mz->len);
|
||||
rte_dump_physmem_layout(stdout);
|
||||
rte_memzone_dump(stdout);
|
||||
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -472,7 +471,6 @@ test_memzone_reserve_max_aligned(void)
|
||||
maxlen, mz->len);
|
||||
rte_dump_physmem_layout(stdout);
|
||||
rte_memzone_dump(stdout);
|
||||
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -683,6 +681,82 @@ test_memzone_bounded(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
test_memzone_free(void)
|
||||
{
|
||||
const struct rte_memzone *mz[RTE_MAX_MEMZONE];
|
||||
int i;
|
||||
char name[20];
|
||||
|
||||
mz[0] = rte_memzone_reserve("tempzone0", 2000, SOCKET_ID_ANY, 0);
|
||||
mz[1] = rte_memzone_reserve("tempzone1", 4000, SOCKET_ID_ANY, 0);
|
||||
|
||||
if (mz[0] > mz[1])
|
||||
return -1;
|
||||
if (!rte_memzone_lookup("tempzone0"))
|
||||
return -1;
|
||||
if (!rte_memzone_lookup("tempzone1"))
|
||||
return -1;
|
||||
|
||||
if (rte_memzone_free(mz[0])) {
|
||||
printf("Fail memzone free - tempzone0\n");
|
||||
return -1;
|
||||
}
|
||||
if (rte_memzone_lookup("tempzone0")) {
|
||||
printf("Found previously free memzone - tempzone0\n");
|
||||
return -1;
|
||||
}
|
||||
mz[2] = rte_memzone_reserve("tempzone2", 2000, SOCKET_ID_ANY, 0);
|
||||
|
||||
if (mz[2] > mz[1]) {
|
||||
printf("tempzone2 should have gotten the free entry from tempzone0\n");
|
||||
return -1;
|
||||
}
|
||||
if (rte_memzone_free(mz[2])) {
|
||||
printf("Fail memzone free - tempzone2\n");
|
||||
return -1;
|
||||
}
|
||||
if (rte_memzone_lookup("tempzone2")) {
|
||||
printf("Found previously free memzone - tempzone2\n");
|
||||
return -1;
|
||||
}
|
||||
if (rte_memzone_free(mz[1])) {
|
||||
printf("Fail memzone free - tempzone1\n");
|
||||
return -1;
|
||||
}
|
||||
if (rte_memzone_lookup("tempzone1")) {
|
||||
printf("Found previously free memzone - tempzone1\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
snprintf(name, sizeof(name), "tempzone%u", i);
|
||||
mz[i] = rte_memzone_reserve(name, 1, SOCKET_ID_ANY, 0);
|
||||
} while (mz[i++] != NULL);
|
||||
|
||||
if (rte_memzone_free(mz[0])) {
|
||||
printf("Fail memzone free - tempzone0\n");
|
||||
return -1;
|
||||
}
|
||||
mz[0] = rte_memzone_reserve("tempzone0new", 0, SOCKET_ID_ANY, 0);
|
||||
|
||||
if (mz[0] == NULL) {
|
||||
printf("Fail to create memzone - tempzone0new - when MAX memzones were "
|
||||
"created and one was free\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = i - 2; i >= 0; i--) {
|
||||
if (rte_memzone_free(mz[i])) {
|
||||
printf("Fail memzone free - tempzone%d\n", i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
test_memzone(void)
|
||||
{
|
||||
@ -763,6 +837,10 @@ test_memzone(void)
|
||||
if (mz != NULL)
|
||||
return -1;
|
||||
|
||||
printf("test free memzone\n");
|
||||
if (test_memzone_free() < 0)
|
||||
return -1;
|
||||
|
||||
printf("test reserving memzone with bigger size than the maximum\n");
|
||||
if (test_memzone_reserving_zone_size_bigger_than_the_maximum() < 0)
|
||||
return -1;
|
||||
|
@ -111,3 +111,9 @@ DPDK_2.0 {
|
||||
|
||||
local: *;
|
||||
};
|
||||
|
||||
DPDK_2.1 {
|
||||
global:
|
||||
|
||||
rte_memzone_free;
|
||||
} DPDK_2.0;
|
||||
|
@ -77,6 +77,23 @@ memzone_lookup_thread_unsafe(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct rte_memzone *
|
||||
get_next_free_memzone(void)
|
||||
{
|
||||
struct rte_mem_config *mcfg;
|
||||
unsigned i = 0;
|
||||
|
||||
/* get pointer to global configuration */
|
||||
mcfg = rte_eal_get_configuration()->mem_config;
|
||||
|
||||
for (i = 0; i < RTE_MAX_MEMZONE; i++) {
|
||||
if (mcfg->memzone[i].addr == NULL)
|
||||
return &mcfg->memzone[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function will return the greatest free block if a heap has been
|
||||
* specified. If no heap has been specified, it will return the heap and
|
||||
* length of the greatest free block available in all heaps */
|
||||
@ -117,7 +134,7 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
|
||||
mcfg = rte_eal_get_configuration()->mem_config;
|
||||
|
||||
/* no more room in config */
|
||||
if (mcfg->memzone_idx >= RTE_MAX_MEMZONE) {
|
||||
if (mcfg->memzone_cnt >= RTE_MAX_MEMZONE) {
|
||||
RTE_LOG(ERR, EAL, "%s(): No more room in config\n", __func__);
|
||||
rte_errno = ENOSPC;
|
||||
return NULL;
|
||||
@ -206,7 +223,16 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
|
||||
const struct malloc_elem *elem = malloc_elem_from_data(mz_addr);
|
||||
|
||||
/* fill the zone in config */
|
||||
struct rte_memzone *mz = &mcfg->memzone[mcfg->memzone_idx++];
|
||||
struct rte_memzone *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;
|
||||
@ -277,6 +303,42 @@ rte_memzone_reserve(const char *name, size_t len, int socket_id,
|
||||
flags, RTE_CACHE_LINE_SIZE, 0);
|
||||
}
|
||||
|
||||
int
|
||||
rte_memzone_free(const struct rte_memzone *mz)
|
||||
{
|
||||
struct rte_mem_config *mcfg;
|
||||
int ret = 0;
|
||||
void *addr;
|
||||
unsigned idx;
|
||||
|
||||
if (mz == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
mcfg = rte_eal_get_configuration()->mem_config;
|
||||
|
||||
rte_rwlock_write_lock(&mcfg->mlock);
|
||||
|
||||
idx = ((uintptr_t)mz - (uintptr_t)mcfg->memzone);
|
||||
idx = idx / sizeof(struct rte_memzone);
|
||||
|
||||
addr = mcfg->memzone[idx].addr;
|
||||
if (addr == NULL)
|
||||
ret = -EINVAL;
|
||||
else if (mcfg->memzone_cnt == 0) {
|
||||
rte_panic("%s(): memzone address not NULL but memzone_cnt is 0!\n",
|
||||
__func__);
|
||||
} else {
|
||||
memset(&mcfg->memzone[idx], 0, sizeof(mcfg->memzone[idx]));
|
||||
mcfg->memzone_cnt--;
|
||||
}
|
||||
|
||||
rte_rwlock_write_unlock(&mcfg->mlock);
|
||||
|
||||
rte_free(addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup for the memzone identified by the given name
|
||||
*/
|
||||
@ -349,7 +411,7 @@ rte_eal_memzone_init(void)
|
||||
rte_rwlock_write_lock(&mcfg->mlock);
|
||||
|
||||
/* delete all zones */
|
||||
mcfg->memzone_idx = 0;
|
||||
mcfg->memzone_cnt = 0;
|
||||
memset(mcfg->memzone, 0, sizeof(mcfg->memzone));
|
||||
|
||||
rte_rwlock_write_unlock(&mcfg->mlock);
|
||||
|
@ -67,7 +67,7 @@ struct rte_mem_config {
|
||||
rte_rwlock_t qlock; /**< used for tailq operation for thread safe. */
|
||||
rte_rwlock_t mplock; /**< only used by mempool LIB for thread-safe. */
|
||||
|
||||
uint32_t memzone_idx; /**< Index of memzone */
|
||||
uint32_t memzone_cnt; /**< Number of allocated memzones */
|
||||
|
||||
/* memory segments and zones */
|
||||
struct rte_memseg memseg[RTE_MAX_MEMSEG]; /**< Physmem descriptors. */
|
||||
|
@ -255,6 +255,17 @@ const struct rte_memzone *rte_memzone_reserve_bounded(const char *name,
|
||||
size_t len, int socket_id,
|
||||
unsigned flags, unsigned align, unsigned bound);
|
||||
|
||||
/**
|
||||
* Free a memzone.
|
||||
*
|
||||
* @param mz
|
||||
* A pointer to the memzone
|
||||
* @return
|
||||
* -EINVAL - invalid parameter
|
||||
* 0 - success
|
||||
*/
|
||||
int rte_memzone_free(const struct rte_memzone *mz);
|
||||
|
||||
/**
|
||||
* Lookup for a memzone.
|
||||
*
|
||||
|
@ -768,12 +768,12 @@ rte_eal_ivshmem_obj_init(void)
|
||||
seg = &ivshmem_config->segment[i];
|
||||
|
||||
/* add memzone */
|
||||
if (mcfg->memzone_idx == RTE_MAX_MEMZONE) {
|
||||
if (mcfg->memzone_cnt == RTE_MAX_MEMZONE) {
|
||||
RTE_LOG(ERR, EAL, "No more memory zones available!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
idx = mcfg->memzone_idx;
|
||||
idx = mcfg->memzone_cnt;
|
||||
|
||||
RTE_LOG(DEBUG, EAL, "Found memzone: '%s' at %p (len 0x%" PRIx64 ")\n",
|
||||
seg->entry.mz.name, seg->entry.mz.addr, seg->entry.mz.len);
|
||||
@ -796,13 +796,13 @@ rte_eal_ivshmem_obj_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
mcfg->memzone_idx++;
|
||||
mcfg->memzone_cnt++;
|
||||
}
|
||||
|
||||
rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
|
||||
|
||||
/* find rings */
|
||||
for (i = 0; i < mcfg->memzone_idx; i++) {
|
||||
for (i = 0; i < mcfg->memzone_cnt; i++) {
|
||||
mz = &mcfg->memzone[i];
|
||||
|
||||
/* check if memzone has a ring prefix */
|
||||
|
@ -111,3 +111,9 @@ DPDK_2.0 {
|
||||
|
||||
local: *;
|
||||
};
|
||||
|
||||
DPDK_2.1 {
|
||||
global:
|
||||
|
||||
rte_memzone_free;
|
||||
} DPDK_2.0;
|
||||
|
Loading…
Reference in New Issue
Block a user