mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
waitpid: use event instead of busy loop when waiting for threads to die
This commit is contained in:
@@ -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;
|
||||
|
||||
+12
-3
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user