From 8100eef0826e7fb182434979a9b139716b3637e1 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 1 Nov 2024 10:12:02 +0200 Subject: speed up creating threads quite a bit --- TODO | 4 +++- arch/riscv64/kernel/vmem.c | 45 +++++++++++++++++++++--------------------- src/tcb.c | 2 -- tests/create-exhaustion/init.c | 3 ++- 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/TODO b/TODO index 73b8040..c80e9b0 100644 --- a/TODO +++ b/TODO @@ -51,7 +51,6 @@ associated program. Easy. (started) + Start working on proper context swaps and RPC swaps. (which thread ID should be visible from cur_tcb() when in an RPC? should I use some kind of effective tid instead of cur_tcb()?) -+ Export VM flags to userspace, separate header or something? + Get core count? It's technically speaking available from the fdt but could be limited by the NR_CPUS macro, so it might be a good idea to export as a CONF_* + The node subsystem might benefit from larger-than-base-page sizes, for example @@ -62,6 +61,9 @@ limited by the NR_CPUS macro, so it might be a good idea to export as a CONF_* just check if the last message is OK, and we only really need more complex checking if we need to calculate like memory leaks etc. ++ grow_rpc() shouldn't exceed limits ++ handle_pagefault() should kill processes that have no good reason to pagefault + !!! FUTURE: + Cache locality? + When mapping some other address space into your own, I could keep a maximum diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c index 4986c1f..bd7906b 100644 --- a/arch/riscv64/kernel/vmem.c +++ b/arch/riscv64/kernel/vmem.c @@ -297,6 +297,9 @@ stat_t map_vpage(struct vmem *branch, pm_t paddr, vm_t vaddr, vmflags_t flags, while (top != order) { size_t idx = vm_to_index(vaddr, top); + /* what if we create one high-level page and a low-level page + * doesn't have enough memory? I think that situation would fail + * the unit tests I currently have */ if (__unused((pm_t)branch->leaf[idx])) { struct vmem *leaf = __create_leaf(); if (!leaf) @@ -602,25 +605,28 @@ stat_t setup_rpc_stack(struct tcb *t) vmflags_t flags = VM_V | VM_R | VM_W; /* note how VM_U is missing, userspace messing about will be done later */ - for (size_t i = 0; i < rpc_pages; ++i) { - pm_t page = alloc_page(BASE_PAGE); - if (!page) - return ERR_OOMEM; - - if (map_vpage(t->rpc.vmem, page, - RPC_STACK_BASE + BASE_PAGE_SIZE * i, - flags, BASE_PAGE)) - return ERR_OOMEM; - } + pm_t page = alloc_page(MM_O1); + if (!page) + return ERR_OOMEM; - /* we allocated a second order page for rpc stack usage */ - t->rpc_stack = RPC_STACK_BASE + order_size(MM_O1); + if (map_vpage(t->rpc.vmem, page, RPC_STACK_BASE, flags, BASE_PAGE)) { + free_page(MM_O1, page); + return ERR_OOMEM; + } - /* slightly hacky maybe but we know the first pte is at RPC_STACK_BASE, - * which means that it must also be the leaf */ t->arch.rpc_leaf = (struct vmem *)__find_vmem(t->rpc.vmem, RPC_STACK_BASE, NULL); + + for (size_t i = 0; i < rpc_pages; ++i) { + t->arch.rpc_leaf->leaf[i] = (struct vmem *)to_pte( + (pm_t)__pa(page + i * BASE_PAGE_SIZE), + vp_flags(flags) + ); + } + + t->rpc_stack = RPC_STACK_BASE + order_size(MM_O1); + /* we count downward in base pages, the top page is *always* reserved */ t->arch.rpc_idx = rpc_pages - 1; /** @todo we could mark the first stack page accessible here already */ @@ -632,14 +638,9 @@ stat_t setup_rpc_stack(struct tcb *t) void destroy_rpc_stack(struct tcb *t) { - for (size_t i = 0; i < rpc_pages; ++i) { - pm_t page = 0; enum mm_order order = BASE_PAGE; - if (stat_vpage(t->rpc.vmem, RPC_STACK_BASE + BASE_PAGE_SIZE * i, - &page, &order, NULL)) - return; - - free_page(order, page); - } + pm_t *pte = (pm_t *)t->arch.rpc_leaf; + pm_t page = (pm_t)pte_addr(*pte); + free_page(MM_O1, page); } void reset_rpc_stack(struct tcb *t) diff --git a/src/tcb.c b/src/tcb.c index ab93f77..06f49db 100644 --- a/src/tcb.c +++ b/src/tcb.c @@ -113,7 +113,6 @@ static stat_t __init_free_thread(struct tcb *t) } if (setup_rpc_stack(t)) { - destroy_rpc_stack(t); destroy_rpcmem(t->rpc.vmem); destroy_vmem(t->proc.vmem); return ERR_OOMEM; @@ -147,7 +146,6 @@ static stat_t __init_owned_thread(struct tcb *p, struct tcb *t) return NULL; if (setup_rpc_stack(t)) { - destroy_rpc_stack(t); destroy_rpcmem(t->rpc.vmem); return ERR_OOMEM; } diff --git a/tests/create-exhaustion/init.c b/tests/create-exhaustion/init.c index d5ac20a..8fc9b1f 100644 --- a/tests/create-exhaustion/init.c +++ b/tests/create-exhaustion/init.c @@ -10,8 +10,9 @@ START(pid, tid, d0, d1, d2, d3) UNUSED(d3); size_t old_ram = 0; + int count = 0; while (1) { - printf("creating new thread\n"); + printf("creating new thread %d\n", count++); id_t new_thread = sys_create((uintptr_t)_start, 1, 2, 3, 4); if (new_thread < 0) break; -- cgit v1.3