diff options
Diffstat (limited to 'sys/kern/kern_spawn.c')
-rw-r--r-- | sys/kern/kern_spawn.c | 79 |
1 files changed, 59 insertions, 20 deletions
diff --git a/sys/kern/kern_spawn.c b/sys/kern/kern_spawn.c index fcaa194..b9551f3 100644 --- a/sys/kern/kern_spawn.c +++ b/sys/kern/kern_spawn.c @@ -28,11 +28,13 @@ */ #include <sys/spawn.h> +#include <sys/wait.h> #include <sys/proc.h> #include <sys/exec.h> #include <sys/mman.h> #include <sys/systm.h> #include <sys/errno.h> +#include <sys/atomic.h> #include <sys/syslog.h> #include <sys/syscall.h> #include <sys/atomic.h> @@ -47,7 +49,8 @@ #define ARGVP_MAX (ARG_MAX / sizeof(void *)) -static volatile size_t nthreads = 0; +static size_t next_pid = 1; +extern volatile size_t g_nthreads; /* * TODO: envp @@ -94,6 +97,35 @@ spawn_thunk(void) __builtin_unreachable(); } +pid_t +waitpid(pid_t pid, int *wstatus, int options) +{ + struct proc *child, *td; + pid_t ret; + + td = this_td(); + child = get_child(td, pid); + + if (child == NULL) { + return -1; + } + + /* Wait for it to be done */ + while (!ISSET(child->flags, PROC_ZOMB)) { + sched_yield(); + } + + + /* Give back the status */ + if (wstatus != NULL) { + copyout(&child->exit_status, wstatus, sizeof(*wstatus)); + } + + ret = child->pid; + proc_reap(child); + return ret; +} + /* * Spawn a new process * @@ -166,28 +198,11 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new newproc->mlgdr = mlgdr; newproc->flags |= PROC_WAITED; - newproc->pid = ++nthreads; + atomic_inc_64(&g_nthreads); + newproc->pid = next_pid++; signals_init(newproc); sched_enqueue_td(newproc); pid = newproc->pid; - - if (ISSET(flags, SPAWN_WAIT)) { - cur->flags |= PROC_SLEEP; - - while (ISSET(cur->flags, PROC_SLEEP)) { - sched_yield(); - } - while (!ISSET(newproc->flags, PROC_ZOMB)) { - sched_yield(); - } - - if (newproc->exit_status < 0) { - pid = newproc->exit_status; - } - - proc_reap(newproc); - } - return pid; } @@ -205,6 +220,9 @@ get_child(struct proc *cur, pid_t pid) struct proc *procp; TAILQ_FOREACH(procp, &cur->leafq, leaf_link) { + if (procp == NULL) { + continue; + } if (procp->pid == pid) { return procp; } @@ -214,6 +232,27 @@ get_child(struct proc *cur, pid_t pid) } /* + * arg0: PID + * arg1: wstatus + * arg2: options + * + * Returns PID of terminated child, returns + * -1 on failure. + */ +scret_t +sys_waitpid(struct syscall_args *scargs) +{ + pid_t pid; + int *u_wstatus; + int options; + + pid = scargs->arg0; + u_wstatus = (void *)scargs->arg1; + options = scargs->arg2; + return waitpid(pid, u_wstatus, options); +} + +/* * arg0: The file /path/to/executable * arg1: Argv * arg2: Envp (TODO) |