summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/include/sys/proc.h12
-rw-r--r--sys/kern/kern_exit.c29
2 files changed, 37 insertions, 4 deletions
diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h
index d252ab7..4024879 100644
--- a/sys/include/sys/proc.h
+++ b/sys/include/sys/proc.h
@@ -63,21 +63,31 @@ struct proc {
struct spinlock vcache_lock;
struct trapframe tf;
struct pcb pcb;
+ struct proc *parent;
size_t priority;
+ int exit_status;
bool rested;
uint32_t flags;
+ uint32_t nleaves;
uintptr_t stack_base;
struct spinlock ksigq_lock;
+ TAILQ_HEAD(, proc) leafq;
+ TAILQ_ENTRY(proc) leaf_link;
TAILQ_HEAD(, ksiginfo) ksigq;
TAILQ_ENTRY(proc) link;
};
#define PROC_EXITING BIT(0) /* Exiting */
#define PROC_EXEC BIT(1) /* Exec called (cleared by sched) */
+#define PROC_ZOMB BIT(2) /* Zombie (dead but not deallocated) */
+#define PROC_LEAFQ BIT(3) /* Leaf queue is active */
+#define PROC_WAITED BIT(4) /* Being waited on by parent */
struct proc *this_td(void);
int md_spawn(struct proc *p, struct proc *parent, uintptr_t ip);
-int spawn(struct proc *cur, int flags, void(*ip)(void), struct proc **newprocp);
+
+scret_t sys_spawn(struct syscall_args *scargs);
+pid_t spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **newprocp);
void md_td_stackinit(struct proc *td, void *stack_top, struct exec_prog *prog);
__dead void md_td_kick(struct proc *td);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 75ab0e9..24c7e74 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -81,7 +81,7 @@ int
exit1(struct proc *td)
{
struct pcb *pcbp;
- struct proc *curtd;
+ struct proc *curtd, *procp;
uintptr_t stack;
pid_t target_pid, curpid;
@@ -93,6 +93,13 @@ exit1(struct proc *td)
stack = td->stack_base;
td->flags |= PROC_EXITING;
+ /* If we have any children, kill them too */
+ if (td->nleaves > 0) {
+ TAILQ_FOREACH(procp, &td->leafq, leaf_link) {
+ exit1(procp);
+ }
+ }
+
/*
* If this is on the higher half, it is kernel
* mapped and we need to convert it to a physical
@@ -107,7 +114,17 @@ exit1(struct proc *td)
vm_free_frame(stack, PROC_STACK_PAGES);
pmap_destroy_vas(pcbp->addrsp);
- dynfree(td);
+
+ /*
+ * Only free the process structure if we aren't
+ * being waited on, otherwise let it be so the
+ * parent can examine what's left of it.
+ */
+ if (!ISSET(td->flags, PROC_WAITED)) {
+ dynfree(td);
+ } else {
+ td->flags |= PROC_ZOMB;
+ }
/*
* If we are the thread exiting, reenter the scheduler
@@ -119,9 +136,15 @@ exit1(struct proc *td)
return 0;
}
+/*
+ * arg0: Exit status.
+ */
scret_t
sys_exit(struct syscall_args *scargs)
{
- exit1(this_td());
+ struct proc *td = this_td();
+
+ td->exit_status = scargs->arg0;
+ exit1(td);
__builtin_unreachable();
}