return sync_memory(va_addr, len, false);
}
+/* detach all EAL memory */
+int
+rte_eal_memory_detach(void)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ size_t page_sz = rte_mem_page_size();
+ unsigned int i;
+
+ rte_rwlock_write_lock(&mcfg->memory_hotplug_lock);
+
+ /* detach internal memory subsystem data first */
+ if (eal_memalloc_cleanup())
+ RTE_LOG(ERR, EAL, "Could not release memory subsystem data\n");
+
+ for (i = 0; i < RTE_DIM(mcfg->memsegs); i++) {
+ struct rte_memseg_list *msl = &mcfg->memsegs[i];
+
+ /* skip uninitialized segments */
+ if (msl->base_va == NULL)
+ continue;
+ /*
+ * external segments are supposed to be detached at this point,
+ * but if they aren't, we can't really do anything about it,
+ * because if we skip them here, they'll become invalid after
+ * we unmap the memconfig anyway. however, if this is externally
+ * referenced memory, we have no business unmapping it.
+ */
+ if (!msl->external)
+ if (rte_mem_unmap(msl->base_va, msl->len) != 0)
+ RTE_LOG(ERR, EAL, "Could not unmap memory: %s\n",
+ strerror(errno));
+
+ /*
+ * we are detaching the fbarray rather than destroying because
+ * other processes might still reference this fbarray, and we
+ * have no way of knowing if they still do.
+ */
+ if (rte_fbarray_detach(&msl->memseg_arr))
+ RTE_LOG(ERR, EAL, "Could not detach fbarray: %s\n",
+ rte_strerror(rte_errno));
+ }
+ rte_rwlock_write_unlock(&mcfg->memory_hotplug_lock);
+
+ /*
+ * we've detached the memseg lists, so we can unmap the shared mem
+ * config - we can't zero it out because it might still be referenced
+ * by other processes.
+ */
+ rte_mem_unmap(mcfg, RTE_ALIGN(sizeof(*mcfg), page_sz));
+ rte_eal_get_configuration()->mem_config = NULL;
+
+ return 0;
+}
+
/* init memory subsystem */
int
rte_eal_memory_init(void)
int
eal_memalloc_init(void);
+int
+eal_memalloc_cleanup(void);
+
#endif /* EAL_MEMALLOC_H */
*/
int rte_eal_hugepage_attach(void);
+/**
+ * Detaches all memory mappings from a process.
+ *
+ * This function is private to the EAL.
+ */
+int rte_eal_memory_detach(void);
+
/**
* Find a bus capable of identifying a device.
*
eal_get_internal_configuration();
rte_service_finalize();
rte_mp_channel_cleanup();
+ /* after this point, any DPDK pointers will become dangling */
+ rte_eal_memory_detach();
rte_trace_save();
eal_trace_fini();
eal_cleanup_config(internal_conf);
return -ENOTSUP;
}
+int eal_memalloc_cleanup(void)
+{
+ return 0;
+}
+
int
eal_memalloc_init(void)
{
rte_memseg_walk(mark_freeable, NULL);
rte_service_finalize();
rte_mp_channel_cleanup();
+ /* after this point, any DPDK pointers will become dangling */
+ rte_eal_memory_detach();
rte_trace_save();
eal_trace_fini();
eal_cleanup_config(internal_conf);
return 0;
}
+static int
+secondary_msl_destroy_walk(const struct rte_memseg_list *msl,
+ void *arg __rte_unused)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ struct rte_memseg_list *local_msl;
+ int msl_idx, ret;
+
+ if (msl->external)
+ return 0;
+
+ msl_idx = msl - mcfg->memsegs;
+ local_msl = &local_memsegs[msl_idx];
+
+ ret = rte_fbarray_destroy(&local_msl->memseg_arr);
+ if (ret < 0) {
+ RTE_LOG(ERR, EAL, "Cannot destroy local memory map\n");
+ return -1;
+ }
+ local_msl->base_va = NULL;
+ local_msl->len = 0;
+
+ return 0;
+}
+
static int
alloc_list(int list_idx, int len)
{
return 0;
}
+static int
+destroy_list(int list_idx)
+{
+ const struct internal_config *internal_conf =
+ eal_get_internal_configuration();
+
+ /* single-file segments mode does not need fd list */
+ if (!internal_conf->single_file_segments) {
+ int *fds = fd_list[list_idx].fds;
+ int i;
+ /* go through each fd and ensure it's closed */
+ for (i = 0; i < fd_list[list_idx].len; i++) {
+ if (fds[i] >= 0) {
+ close(fds[i]);
+ fds[i] = -1;
+ }
+ }
+ free(fds);
+ fd_list[list_idx].fds = NULL;
+ fd_list[list_idx].len = 0;
+ } else if (fd_list[list_idx].memseg_list_fd >= 0) {
+ close(fd_list[list_idx].memseg_list_fd);
+ fd_list[list_idx].count = 0;
+ fd_list[list_idx].memseg_list_fd = -1;
+ }
+ return 0;
+}
+
static int
fd_list_create_walk(const struct rte_memseg_list *msl,
void *arg __rte_unused)
return alloc_list(msl_idx, len);
}
+static int
+fd_list_destroy_walk(const struct rte_memseg_list *msl, void *arg __rte_unused)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ int msl_idx;
+
+ if (msl->external)
+ return 0;
+
+ msl_idx = msl - mcfg->memsegs;
+
+ return destroy_list(msl_idx);
+}
+
int
eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd)
{
return 0;
}
+int
+eal_memalloc_cleanup(void)
+{
+ /* close all remaining fd's - these are per-process, so it's safe */
+ if (rte_memseg_list_walk_thread_unsafe(fd_list_destroy_walk, NULL))
+ return -1;
+
+ /* destroy the shadow page table if we're a secondary process */
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ return 0;
+
+ if (rte_memseg_list_walk_thread_unsafe(secondary_msl_destroy_walk,
+ NULL))
+ return -1;
+
+ return 0;
+}
+
int
eal_memalloc_init(void)
{
{
struct internal_config *internal_conf =
eal_get_internal_configuration();
-
+ /* after this point, any DPDK pointers will become dangling */
+ rte_eal_memory_detach();
eal_cleanup_config(internal_conf);
return 0;
}
return -1;
}
+int
+eal_memalloc_cleanup(void)
+{
+ /* not implemented */
+ return 0;
+}
+
int
eal_memalloc_init(void)
{