diff options
-rw-r--r-- | sys/include/sys/spawn.h | 3 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 10 | ||||
-rw-r--r-- | sys/kern/kern_spawn.c | 21 |
3 files changed, 33 insertions, 1 deletions
diff --git a/sys/include/sys/spawn.h b/sys/include/sys/spawn.h index 3828d5c..9d823db 100644 --- a/sys/include/sys/spawn.h +++ b/sys/include/sys/spawn.h @@ -31,6 +31,9 @@ #define _SYS_SPAWN_H_ #include <sys/types.h> +#include <sys/param.h> + +#define SPAWN_WAIT BIT(0) #if !defined(_KERNEL) pid_t spawn(const char *pathname, int flags); diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index a421e52..b6cbc4e 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -111,6 +111,7 @@ int exit1(struct proc *td, int flags) { struct proc *curtd, *procp; + struct proc *parent; struct cpu_info *ci; pid_t target_pid, curpid; @@ -120,6 +121,7 @@ exit1(struct proc *td, int flags) curpid = curtd->pid; td->flags |= PROC_EXITING; + parent = td->parent; /* If we have any children, kill them too */ if (td->nleaves > 0) { @@ -149,6 +151,13 @@ exit1(struct proc *td, int flags) */ if (target_pid == curpid) { ci->curtd = NULL; + if (parent->pid == 0) + sched_enter(); + if (td->data == NULL) + sched_enter(); + + sched_enqueue_td(parent); + parent->flags &= ~PROC_SLEEP; sched_enter(); } @@ -163,6 +172,7 @@ sys_exit(struct syscall_args *scargs) { struct proc *td = this_td(); + td->data = scargs->tf; td->exit_status = scargs->arg0; exit1(td, 0); __builtin_unreachable(); diff --git a/sys/kern/kern_spawn.c b/sys/kern/kern_spawn.c index 3360443..d72eeae 100644 --- a/sys/kern/kern_spawn.c +++ b/sys/kern/kern_spawn.c @@ -111,6 +111,7 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new struct proc *newproc; struct mmap_lgdr *mlgdr; int error; + pid_t pid; newproc = dynalloc(sizeof(*newproc)); if (newproc == NULL) { @@ -161,7 +162,25 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new newproc->pid = ++nthreads; signals_init(newproc); sched_enqueue_td(newproc); - return newproc->pid; + pid = newproc->pid; + + if (ISSET(flags, SPAWN_WAIT)) { + newproc->flags |= PROC_WAITED; + cur->flags |= PROC_SLEEP; + + while (ISSET(cur->flags, PROC_SLEEP)) { + sched_yield(); + } + + if (!ISSET(newproc->flags, PROC_ZOMB)) { + pr_error("spawn: fatal: %d not zombie\n"); + panic("possibly memory corruption\n"); + } + + proc_reap(newproc); + } + + return pid; } /* |