From 9c0f26d26366ff7def20d5be6aff5e0f93976ad6 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 6 Jul 2024 20:50:36 +0300 Subject: adjust stack handling --- arch/riscv64/kernel/proc.c | 6 +++--- arch/riscv64/kernel/vmem.c | 7 +++++++ include/arch/tcb.h | 7 +++++++ include/kmi/tcb.h | 16 +++++++++------- src/orphanage.c | 7 ++++++- src/tcb.c | 28 ++++++++++++++++++---------- 6 files changed, 50 insertions(+), 21 deletions(-) diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c index f1a62c4..a4746b4 100644 --- a/arch/riscv64/kernel/proc.c +++ b/arch/riscv64/kernel/proc.c @@ -28,6 +28,7 @@ void run_init(struct tcb *t, vm_t fdt, vm_t initrd) * Could be fixed with a separate pure asm run_init, but I guess this * works for now. */ + vm_t stack_top = t->thread_stack + t->thread_stack_size; bkl_unlock(); __asm__ volatile ("mv sp, %0\n" "mv a0, %1\n" @@ -35,7 +36,7 @@ void run_init(struct tcb *t, vm_t fdt, vm_t initrd) "mv a2, %3\n" "sret\n" : - : "r" (t->thread_stack_top), "r" (t->tid), "r" (fdt), + : "r" (stack_top), "r" (t->tid), "r" (fdt), "r" (initrd) : "memory"); /* we should never reach this */ @@ -66,8 +67,7 @@ void set_thread(struct tcb *t) struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1; /* insert important values into register slots */ - r->sp = (long)t->thread_stack_top; - r->tp = (long)t->thread_storage; + r->sp = (long)t->thread_stack + t->thread_stack_size; } void set_stack(struct tcb *t, vm_t s) diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c index f717771..00752c1 100644 --- a/arch/riscv64/kernel/vmem.c +++ b/arch/riscv64/kernel/vmem.c @@ -551,11 +551,18 @@ void destroy_rpc_stack(struct tcb *t) } } +void reset_rpc_stack(struct tcb *t) +{ + t->rpc_stack = RPC_STACK_BASE + (BASE_PAGE_SIZE * rpc_pages); + t->arch.rpc_idx = rpc_pages; +} + bool rpc_stack_empty(pm_t addr) { return addr == RPC_STACK_BASE + (BASE_PAGE_SIZE * rpc_pages); } + vm_t rpc_position(struct tcb *t) { /** @todo we assume rpc_idx is updated on every segfault of the rpc stack */ diff --git a/include/arch/tcb.h b/include/arch/tcb.h index 931b800..b8b0961 100644 --- a/include/arch/tcb.h +++ b/include/arch/tcb.h @@ -41,6 +41,13 @@ void setup_rpc_stack(struct tcb *t); */ void destroy_rpc_stack(struct tcb *t); +/** + * Reset RPC stack to top. + * + * @param t Thread whose RPC stack should be reset. + */ +void reset_rpc_stack(struct tcb *t); + /** * @return Max size of one individual RPC stack instance. */ diff --git a/include/kmi/tcb.h b/include/kmi/tcb.h index b7fd3d6..a06d801 100644 --- a/include/kmi/tcb.h +++ b/include/kmi/tcb.h @@ -122,18 +122,13 @@ struct tcb { vm_t thread_stack; /** Address of this thread's stack top. */ - vm_t thread_stack_top; + vm_t thread_stack_size; /** Current address of usable rpc stack. */ vm_t rpc_stack; - /** \todo Check if each thread should be allowed more than just one - * region of thread local storage. */ - /** Possible thread local storage. */ - vm_t thread_storage; - /** Reference count to process. */ - atomic_int_fast32_t refcount; + long refcount; /** Process context of thread. */ struct tcb_ctx proc; @@ -321,6 +316,13 @@ struct tcb *get_tcb(id_t tid); */ stat_t alloc_stack(struct tcb *t); +/** + * Free thread stack. + * + * @param t Thread whose stack to free. + */ +void free_stack(struct tcb *t); + /** * Set address to jump to when returning to userspace. * diff --git a/src/orphanage.c b/src/orphanage.c index 4760f73..9da6f8b 100644 --- a/src/orphanage.c +++ b/src/orphanage.c @@ -34,9 +34,14 @@ void unorphanize(struct tcb *t) t->pid = 1; t->eid = 1; + free_stack(t); + reset_rpc_stack(t); + t->proc = init->proc; - t->rpc_stack = RPC_STACK_BASE; use_vmem(t->proc.vmem); + alloc_stack(t); + + clear_bits(t->state, TCB_ORPHAN); catastrophic_assert(init->callback); set_args3(t, 0, SYS_USER_ORPHANED, t->tid); diff --git a/src/tcb.c b/src/tcb.c index 51aa939..45c31ce 100644 --- a/src/tcb.c +++ b/src/tcb.c @@ -107,11 +107,17 @@ stat_t alloc_stack(struct tcb *t) return ERR_OOMEM; /** \todo this only allows for a global stack size, what if a user wants - * per thread stack sizes? */ - t->thread_stack_top = t->thread_stack + __thread_stack_size; + * per thread stack sizes? I guess allocate them yourself in userspace + * or something? */ + t->thread_stack_size = __thread_stack_size; return OK; } +void free_stack(struct tcb *t) +{ + free_uvmem(t, t->thread_stack); +} + struct tcb *create_thread(struct tcb *p) { hard_assert(tcbs, 0); @@ -171,7 +177,7 @@ static stat_t __copy_proc(struct tcb *p, struct tcb *n) n->exec = p->exec; n->callback = p->callback; n->thread_stack = p->thread_stack; - n->thread_stack_top = p->thread_stack_top; + n->thread_stack_size = p->thread_stack_size; copy_regs(n, p); copy_caps(n->caps, p->caps); @@ -188,7 +194,7 @@ struct tcb *create_proc(struct tcb *p) return 0; if (p) - __copy_proc(p, n); /* we have a parent thread */ + __copy_proc(p, n); /* we have a parent process i.e. fork */ return n; } @@ -203,12 +209,6 @@ static stat_t __destroy_thread_data(struct tcb *t) { catastrophic_assert(t->refcount == 0); - /* free memory backing rpc stack */ - destroy_rpc_stack(t); - - /* free rpc vmem */ - destroy_vmem(t->rpc.vmem); - /* remove ourselves from the thread pool */ /** @todo this should be at the top of the function, and be wrapped in * some kind of lock that checks that nobody reads the value while we're @@ -241,6 +241,14 @@ stat_t destroy_thread(struct tcb *t) /* remove reference to root process */ unreference_proc(get_rproc(t)); + free_stack(t); + + /* free memory backing rpc stack */ + destroy_rpc_stack(t); + + /* free rpc vmem */ + destroy_vmem(t->rpc.vmem); + unqueue_ipi(t); /** @todo timers, irqs? theoretically we could allow them to stay and -- cgit v1.3