From 3dfb6b5a8cea3724309c1c90cf3d6dc2d3481e76 Mon Sep 17 00:00:00 2001 From: Matheus Date: Thu, 16 Apr 2026 22:41:43 -0300 Subject: [PATCH] waitpid: use event instead of busy loop when waiting for threads to die --- kernel-src/include/kernel/proc.h | 1 + kernel-src/sys/proc.c | 15 ++++++++++++--- kernel-src/sys/syscalls/waitpid.c | 15 ++++++++++++--- kernel-src/sys/thread.c | 2 ++ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/kernel-src/include/kernel/proc.h b/kernel-src/include/kernel/proc.h index c251162b..26bf232f 100644 --- a/kernel-src/include/kernel/proc.h +++ b/kernel-src/include/kernel/proc.h @@ -36,6 +36,7 @@ typedef struct proc_t { cred_t cred; spinlock_t threadlistlock; thread_t *threadlist; + eventheader_t thread_exit_event; bool nomorethreads; size_t runningthreadcount; size_t fdcount; diff --git a/kernel-src/sys/proc.c b/kernel-src/sys/proc.c index 6ab27f91..f1fbdaf0 100644 --- a/kernel-src/sys/proc.c +++ b/kernel-src/sys/proc.c @@ -107,6 +107,7 @@ proc_t *proc_create() { itimer_init(&proc->timer.profiling, profdpc, proc); SPINLOCK_INIT(proc->threadlistlock); EVENT_INITHEADER(&proc->child_exit_event); + EVENT_INITHEADER(&proc->thread_exit_event); proc->fd = alloc(sizeof(fd_t) * 3); if (proc->fd == NULL) { @@ -173,10 +174,18 @@ void proc_stop_other_threads() { threadlist = threadlist->procnext; } - while (__atomic_load_n(&proc->runningthreadcount, __ATOMIC_SEQ_CST) > 1) { - arch_e9_puts("proc_stop_other_threads\n"); - sched_yield(); + eventlistener_t listener; + EVENT_INITLISTENER(&listener); + for (;;) { + EVENT_ATTACH(&listener, &proc->thread_exit_event); + if (__atomic_load_n(&proc->runningthreadcount, __ATOMIC_SEQ_CST) == 1) + break; + + EVENT_WAIT(&listener, 0); + EVENT_DETACHALL(&listener); } + EVENT_DETACHALL(&listener); + proc->nomorethreads = false; } diff --git a/kernel-src/sys/syscalls/waitpid.c b/kernel-src/sys/syscalls/waitpid.c index dcb9a885..fb1ab756 100644 --- a/kernel-src/sys/syscalls/waitpid.c +++ b/kernel-src/sys/syscalls/waitpid.c @@ -132,10 +132,19 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt while (threadlist) { thread_t *freethread = threadlist; threadlist = threadlist->procnext; - volatile int *flags = (volatile int *)(&freethread->flags); // wait until the thread can actually be unallocated - while ((*flags & THREAD_FLAGS_DEAD) == 0) - sched_yield(); + eventlistener_t listener; + EVENT_INITLISTENER(&listener); + for (;;) { + EVENT_ATTACH(&listener, &iterator->thread_exit_event); + if (freethread->flags & THREAD_FLAGS_DEAD) { + EVENT_DETACHALL(&listener); + break; + } + + EVENT_WAIT(&listener, 0); + EVENT_DETACHALL(&listener); + } sched_destroythread(freethread); } diff --git a/kernel-src/sys/thread.c b/kernel-src/sys/thread.c index fdbb16f8..e1fee627 100644 --- a/kernel-src/sys/thread.c +++ b/kernel-src/sys/thread.c @@ -70,6 +70,8 @@ static void threadexit_internal(context_t *, void *) { current_cpu()->thread = NULL; thread->flags |= THREAD_FLAGS_DEAD; + if (thread->proc) + EVENT_SIGNAL(&thread->proc->thread_exit_event); // because a thread deallocating its own data is a nightmare, thread deallocation and such will be left to whoever frees the proc it's tied to // (likely an exit(2) call)