From f59c3b52c520a7c024743ffac94fa7f62eadcd26 Mon Sep 17 00:00:00 2001 From: Sparchatus Date: Thu, 5 May 2022 09:21:30 +0000 Subject: [PATCH] Free paging slab space used in spawning a child process --- include/aos/paging.h | 8 ++++++++ lib/aos/paging.c | 28 ++++++++++++++++++++++++++++ lib/spawn/spawn.c | 4 ++++ 3 files changed, 40 insertions(+) diff --git a/include/aos/paging.h b/include/aos/paging.h index 1a996fc..92c8933 100644 --- a/include/aos/paging.h +++ b/include/aos/paging.h @@ -135,4 +135,12 @@ static inline lvaddr_t paging_genvaddr_to_lvaddr(genvaddr_t genvaddr) { // NOTE rueegges: added debug helper void pt_print_state(struct paging_state *st); +/** + * @brief Destructive action! NOT THREAD SAFE + * This frees all the slab space occupied by the given paging state without performing any unmapping operations + * + * @param st paging state to perform destructive action on + */ +void paging_free_slabs(struct paging_state *st); + #endif // LIBBARRELFISH_PAGING_H diff --git a/lib/aos/paging.c b/lib/aos/paging.c index 7b14290..4aac581 100644 --- a/lib/aos/paging.c +++ b/lib/aos/paging.c @@ -1049,3 +1049,31 @@ errval_t paging_unmap(struct paging_state *st, const void *region) return err; } + +/** + * @brief Function to recursively free all the slab space. NOT THREAD SAFE + * + * @param pt page table to recursively free the slab space for + * @return errval_t + */ +static void paging_free_page_table_tree(struct paging_state *st, struct pt_t *pt) { + if(pt == NULL) return; + if(pt->children != NULL) { + for(size_t i = 0; i < PTABLE_ENTRIES; ++i) { + paging_free_page_table_tree(st, pt->children[i]); + } + slab_free(&st->pt_children_slabs, pt->children); + } + slab_free(&st->pt_slabs, pt); +} + +void paging_free_slabs(struct paging_state *st) { + // free the slab space used by the child paging state so it can be reused by the parent + for(size_t i = 0; i < PTABLE_ENTRIES; ++i){ + paging_free_page_table_tree(st, st->l0_pt.children[i]); + } + for(struct pt_vaddr_reg_t *reg = st->vaddr_head.next; reg != NULL; reg = reg->next){ + slab_free(&st->pt_slabs, reg); + } + +} \ No newline at end of file diff --git a/lib/spawn/spawn.c b/lib/spawn/spawn.c index 6169d66..95499e0 100644 --- a/lib/spawn/spawn.c +++ b/lib/spawn/spawn.c @@ -511,6 +511,9 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, struct paging_state *child_paging_state = &_child_paging_state; // 64 * 1024 is enough to catch null pointers and also enough to not conflict with child starting paging_alloc at VADDR_OFFSET err = paging_init_state_foreign(child_paging_state, VADDR_LOWEST_NON_NULL, si->vspace_cap_l0_pagetable, get_default_slot_allocator()); + // we use the parent's slab allocators because we want to later free the child paging state's memory + child_paging_state->pt_slabs = get_current_paging_state()->pt_slabs; + child_paging_state->pt_children_slabs = get_current_paging_state()->pt_children_slabs; if (err_is_fail(err)) return err_push(err, SPAWN_ERR_PAGING_INIT); // - Load the ELF binary @@ -641,6 +644,7 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si, if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_SERIALISE_VSPACE); } + paging_free_slabs(child_paging_state); // so we don't use it after serializing child_paging_state = NULL;