diff options
Diffstat (limited to 'sys/kern/kern_exit.c')
-rw-r--r-- | sys/kern/kern_exit.c | 69 |
1 files changed, 49 insertions, 20 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index d6c9168..b6cbc4e 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -35,6 +35,7 @@ #include <vm/vm.h> #include <vm/map.h> #include <machine/pcb.h> +#include <machine/cpu.h> #define pr_trace(fmt, ...) kprintf("exit: " fmt, ##__VA_ARGS__) #define pr_error(...) pr_trace(__VA_ARGS__) @@ -49,6 +50,10 @@ unload_td(struct proc *td) size_t len; sched_detach(td); + if (ISSET(td->flags, PROC_KTD)) { + return; + } + execp = &td->exec; auxvalp = &execp->auxval; pcbp = &td->pcb; @@ -73,48 +78,62 @@ unload_td(struct proc *td) } } +void +proc_reap(struct proc *td) +{ + struct pcb *pcbp; + uintptr_t stack; + + pcbp = &td->pcb; + stack = td->stack_base; + + /* + * If this is on the higher half, it is kernel + * mapped and we need to convert it to a physical + * address. + */ + if (stack >= VM_HIGHER_HALF) { + stack -= VM_HIGHER_HALF; + } + + unload_td(td); + vm_unmap(pcbp->addrsp, td->stack_base, PROC_STACK_SIZE); + vm_free_frame(stack, PROC_STACK_PAGES); + pmap_destroy_vas(pcbp->addrsp); +} + /* * Kill a thread and deallocate its resources. * * @td: Thread to exit */ int -exit1(struct proc *td) +exit1(struct proc *td, int flags) { - struct pcb *pcbp; struct proc *curtd, *procp; - uintptr_t stack; + struct proc *parent; + struct cpu_info *ci; pid_t target_pid, curpid; + ci = this_cpu(); target_pid = td->pid; curtd = this_td(); - pcbp = &td->pcb; curpid = curtd->pid; - stack = td->stack_base; td->flags |= PROC_EXITING; + parent = td->parent; /* If we have any children, kill them too */ if (td->nleaves > 0) { TAILQ_FOREACH(procp, &td->leafq, leaf_link) { - exit1(procp); + exit1(procp, flags); } } - /* - * If this is on the higher half, it is kernel - * mapped and we need to convert it to a physical - * address. - */ - if (stack >= VM_HIGHER_HALF) { - stack -= VM_HIGHER_HALF; + if (target_pid != curpid) { + proc_reap(td); } - unload_td(td); - vm_unmap(pcbp->addrsp, td->stack_base, PROC_STACK_SIZE); - vm_free_frame(stack, PROC_STACK_PAGES); - pmap_destroy_vas(pcbp->addrsp); - /* * Only free the process structure if we aren't * being waited on, otherwise let it be so the @@ -130,8 +149,17 @@ exit1(struct proc *td) * If we are the thread exiting, reenter the scheduler * and do not return. */ - if (target_pid == curpid) + 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(); + } return 0; } @@ -144,7 +172,8 @@ sys_exit(struct syscall_args *scargs) { struct proc *td = this_td(); + td->data = scargs->tf; td->exit_status = scargs->arg0; - exit1(td); + exit1(td, 0); __builtin_unreachable(); } |