printf("Expected size = %zu, actual size = %zu\n", maxlen, mz->len);
rte_dump_physmem_layout(stdout);
rte_memzone_dump(stdout);
-
return -1;
}
return 0;
maxlen, mz->len);
rte_dump_physmem_layout(stdout);
rte_memzone_dump(stdout);
-
return -1;
}
return 0;
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)
{
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;
local: *;
};
+
+DPDK_2.1 {
+ global:
+
+ rte_memzone_free;
+} DPDK_2.0;
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 */
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;
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;
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
*/
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);
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. */
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.
*
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);
}
}
- 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 */
local: *;
};
+
+DPDK_2.1 {
+ global:
+
+ rte_memzone_free;
+} DPDK_2.0;