diff --git a/kernel-src/include/kernel/proc.h b/kernel-src/include/kernel/proc.h index d531741c..c251162b 100644 --- a/kernel-src/include/kernel/proc.h +++ b/kernel-src/include/kernel/proc.h @@ -31,6 +31,7 @@ typedef struct proc_t { struct proc_t *sibling; struct proc_t *parent; struct proc_t *child; + eventheader_t child_exit_event; pid_t pid; cred_t cred; spinlock_t threadlistlock; @@ -46,7 +47,6 @@ typedef struct proc_t { vnode_t *cwd; vnode_t *root; spinlock_t nodeslock; - semaphore_t waitsem; spinlock_t exiting; int nice; diff --git a/kernel-src/sys/proc.c b/kernel-src/sys/proc.c index 27407f29..6ab27f91 100644 --- a/kernel-src/sys/proc.c +++ b/kernel-src/sys/proc.c @@ -98,7 +98,6 @@ proc_t *proc_create() { proc->refcount = 1; proc->fdfirst = 3; MUTEX_INIT(&proc->fdmutex); - SEMAPHORE_INIT(&proc->waitsem, 0); SPINLOCK_INIT(proc->jobctllock); SPINLOCK_INIT(proc->pgrp.lock); SPINLOCK_INIT(proc->signals.lock); @@ -107,6 +106,7 @@ proc_t *proc_create() { itimer_init(&proc->timer.virtualtime, vtdpc, proc); itimer_init(&proc->timer.profiling, profdpc, proc); SPINLOCK_INIT(proc->threadlistlock); + EVENT_INITHEADER(&proc->child_exit_event); proc->fd = alloc(sizeof(fd_t) * 3); if (proc->fd == NULL) { @@ -299,10 +299,10 @@ void proc_exit(void) { MUTEX_RELEASE(&proc->mutex); signal_signalproc(proc->parent, SIGCHLD); - semaphore_signal(&proc->parent->waitsem); + EVENT_SIGNAL(&proc->parent->child_exit_event); // TODO sigaction flag for this - for (int i = 0; i < belowzombiecount; ++i) { - semaphore_signal(&init_proc->waitsem); + if (belowzombiecount) { + EVENT_SIGNAL(&init_proc->child_exit_event); } } diff --git a/kernel-src/sys/signal.c b/kernel-src/sys/signal.c index 5226e28e..398e1cfc 100644 --- a/kernel-src/sys/signal.c +++ b/kernel-src/sys/signal.c @@ -411,7 +411,8 @@ void signal_signalproc(struct proc_t *proc, int signal) { if (proc->parent && (proc->parent->signals.actions[SIGCHLD].flags & SA_NOCLDSTOP) == 0) { signal_signalproc(proc->parent, SIGCHLD); } - semaphore_signal(&proc->parent->waitsem); + + EVENT_SIGNAL(&proc->parent->child_exit_event); } // tell the parent that a child continued @@ -423,7 +424,7 @@ void signal_signalproc(struct proc_t *proc, int signal) { signal_signalproc(proc->parent, SIGCHLD); } - semaphore_signal(&proc->parent->waitsem); + EVENT_SIGNAL(&proc->parent->child_exit_event); } } diff --git a/kernel-src/sys/syscalls/waitpid.c b/kernel-src/sys/syscalls/waitpid.c index 0151ee63..dcb9a885 100644 --- a/kernel-src/sys/syscalls/waitpid.c +++ b/kernel-src/sys/syscalls/waitpid.c @@ -11,7 +11,6 @@ #define WCONTINUED 8 #define KNOWN_FLAGS (WNOHANG | WSTOPPED | WCONTINUED | __WALL) -// TODO use events here syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int options) { syscallret_t ret = { .ret = -1 @@ -44,6 +43,8 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt bool continued = false; bool stopped = false; bool zombie = false; + eventlistener_t listener; + EVENT_INITLISTENER(&listener); for (;;) { if (iterator == NULL) { @@ -52,15 +53,22 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt MUTEX_RELEASE(&proc->mutex); return ret; } - MUTEX_RELEASE(&proc->mutex); - if ((options & WNOHANG) && semaphore_test(&proc->waitsem) == false) { + + if (options & WNOHANG) { + MUTEX_RELEASE(&proc->mutex); ret.errno = 0; ret.ret = 0; return ret; - } else if ((options & WNOHANG) == 0 && semaphore_wait(&proc->waitsem, true)) { - ret.errno = EINTR; - return ret; } + + EVENT_ATTACH(&listener, &proc->child_exit_event); + MUTEX_RELEASE(&proc->mutex); + + ret.errno = EVENT_WAIT(&listener, 0); + EVENT_DETACHALL(&listener); + if (ret.errno) + return ret; + MUTEX_ACQUIRE(&proc->mutex); prev = NULL; iterator = proc->child;