summaryrefslogtreecommitdiff
path: root/sys/kern/kern_spawn.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_spawn.c')
-rw-r--r--sys/kern/kern_spawn.c79
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)