From 8d8b319319f1528d6ee79a7fd18d6c6c779aeb81 Mon Sep 17 00:00:00 2001 From: Matheus Date: Mon, 21 Nov 2022 20:12:47 -0300 Subject: [PATCH] sched: handle thread death in a less hacky way --- src/include/kernel/sched.h | 1 + src/sys/syscalls/exit.c | 5 ---- src/sys/syscalls/waitpid.c | 50 ++++++++++++++++++++++++++++++++------ 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/include/kernel/sched.h b/src/include/kernel/sched.h index c5880c77..4e18b099 100644 --- a/src/include/kernel/sched.h +++ b/src/include/kernel/sched.h @@ -18,6 +18,7 @@ #define THREAD_STATE_BLOCKED 2 #define THREAD_STATE_BLOCKED_INTR 3 #define THREAD_STATE_DEAD 4 +#define THREAD_STATE_DESTROYED 5 #define PROC_STATE_NORMAL 0 #define PROC_STATE_ZOMBIE 1 diff --git a/src/sys/syscalls/exit.c b/src/sys/syscalls/exit.c index d16189e7..6efe8237 100644 --- a/src/sys/syscalls/exit.c +++ b/src/sys/syscalls/exit.c @@ -49,11 +49,6 @@ void syscall_exit(int status){ event_signal(&proc->parent->childevent, true); - // context and thread destruction will happen in the waitpid() - // the pointer to this thread will reside in proc->threads - - proc->threads = arch_getcls()->thread; - arch_interrupt_disable(); spinlock_release(&proc->lock); diff --git a/src/sys/syscalls/waitpid.c b/src/sys/syscalls/waitpid.c index 559063c1..1e091e76 100644 --- a/src/sys/syscalls/waitpid.c +++ b/src/sys/syscalls/waitpid.c @@ -8,6 +8,7 @@ #include #include #include +#include #define UNSUPPORTED "astral: waitpid: Unsupported waitpid options!\n" #define UNSUPPORTED_PG "astral: waitpid: Process group waits are not supported yet.\n" @@ -96,15 +97,48 @@ syscallret syscall_waitpid(pid_t pid, int *status, int options){ if(status) *status = child->status; // XXX safer way of doing this - // the pointer to the last remaining thread is is proc->threads - - thread_t* thread = child->threads; - + int threadc = proc->threadcount; - free(thread->regs); - free(thread->kernelstackbase); - vmm_destroy(thread->ctx); - free(thread); + // free all the threads + + while(proc->threadcount){ + + for(int t = 0; t < threadc; ++t){ + + thread_t* thread = proc->threads[t]; + + // XXX possible race condition here? + + if(thread->state != THREAD_STATE_DEAD) + continue; + + free(thread->regs); + free(thread->kernelstackbase); + vmm_destroy(thread->ctx); + + thread->state = THREAD_STATE_DESTROYED; + + } + + arch_interrupt_disable(); + + sched_yield(); + + arch_interrupt_enable(); + + } + + for(int t = 0; t < threadc; ++t){ + + thread_t* thread = proc->threads[t]; + + if(thread->state != THREAD_STATE_DESTROYED) + _panic("Freeing non-destroyed thread", NULL); + + free(thread); + + } + free(child); retv.ret = child->pid;