mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 15:08:21 +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;
|
cred_t cred;
|
||||||
spinlock_t threadlistlock;
|
spinlock_t threadlistlock;
|
||||||
thread_t *threadlist;
|
thread_t *threadlist;
|
||||||
|
eventheader_t thread_exit_event;
|
||||||
bool nomorethreads;
|
bool nomorethreads;
|
||||||
size_t runningthreadcount;
|
size_t runningthreadcount;
|
||||||
size_t fdcount;
|
size_t fdcount;
|
||||||
|
|||||||
+12
-3
@@ -107,6 +107,7 @@ proc_t *proc_create() {
|
|||||||
itimer_init(&proc->timer.profiling, profdpc, proc);
|
itimer_init(&proc->timer.profiling, profdpc, proc);
|
||||||
SPINLOCK_INIT(proc->threadlistlock);
|
SPINLOCK_INIT(proc->threadlistlock);
|
||||||
EVENT_INITHEADER(&proc->child_exit_event);
|
EVENT_INITHEADER(&proc->child_exit_event);
|
||||||
|
EVENT_INITHEADER(&proc->thread_exit_event);
|
||||||
|
|
||||||
proc->fd = alloc(sizeof(fd_t) * 3);
|
proc->fd = alloc(sizeof(fd_t) * 3);
|
||||||
if (proc->fd == NULL) {
|
if (proc->fd == NULL) {
|
||||||
@@ -173,10 +174,18 @@ void proc_stop_other_threads() {
|
|||||||
threadlist = threadlist->procnext;
|
threadlist = threadlist->procnext;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (__atomic_load_n(&proc->runningthreadcount, __ATOMIC_SEQ_CST) > 1) {
|
eventlistener_t listener;
|
||||||
arch_e9_puts("proc_stop_other_threads\n");
|
EVENT_INITLISTENER(&listener);
|
||||||
sched_yield();
|
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;
|
proc->nomorethreads = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,10 +132,19 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt
|
|||||||
while (threadlist) {
|
while (threadlist) {
|
||||||
thread_t *freethread = threadlist;
|
thread_t *freethread = threadlist;
|
||||||
threadlist = threadlist->procnext;
|
threadlist = threadlist->procnext;
|
||||||
volatile int *flags = (volatile int *)(&freethread->flags);
|
|
||||||
// wait until the thread can actually be unallocated
|
// wait until the thread can actually be unallocated
|
||||||
while ((*flags & THREAD_FLAGS_DEAD) == 0)
|
eventlistener_t listener;
|
||||||
sched_yield();
|
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);
|
sched_destroythread(freethread);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ static void threadexit_internal(context_t *, void *) {
|
|||||||
current_cpu()->thread = NULL;
|
current_cpu()->thread = NULL;
|
||||||
|
|
||||||
thread->flags |= THREAD_FLAGS_DEAD;
|
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
|
// 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)
|
// (likely an exit(2) call)
|
||||||
|
|||||||
Reference in New Issue
Block a user