aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-11-01 10:12:02 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2024-11-01 10:28:16 +0200
commit8100eef0826e7fb182434979a9b139716b3637e1 (patch)
tree991324108d849a9bc825528fbba38fb4a887cd11
parent9914b44878ca52cc615d2f4e47fec400dd55ab76 (diff)
downloadkmi-8100eef0826e7fb182434979a9b139716b3637e1.tar.gz
kmi-8100eef0826e7fb182434979a9b139716b3637e1.zip
speed up creating threads quite a bit
-rw-r--r--TODO4
-rw-r--r--arch/riscv64/kernel/vmem.c43
-rw-r--r--src/tcb.c2
-rw-r--r--tests/create-exhaustion/init.c3
4 files changed, 27 insertions, 25 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;
+ pm_t page = alloc_page(MM_O1);
+ 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;
+ if (map_vpage(t->rpc.vmem, page, RPC_STACK_BASE, flags, BASE_PAGE)) {
+ free_page(MM_O1, page);
+ return ERR_OOMEM;
}
- /* we allocated a second order page for rpc stack usage */
- t->rpc_stack = RPC_STACK_BASE + order_size(MM_O1);
-
- /* 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;