1996c772fSJohn Dyson /* 2df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1989, 1991, 1993 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * (c) UNIX System Laboratories, Inc. 5df8bae1dSRodney W. Grimes * All or some portions of this file are derived from material licensed 6df8bae1dSRodney W. Grimes * to the University of California by American Telephone and Telegraph 7df8bae1dSRodney W. Grimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8df8bae1dSRodney W. Grimes * the permission of UNIX System Laboratories, Inc. 9df8bae1dSRodney W. Grimes * 10df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 11df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 12df8bae1dSRodney W. Grimes * are met: 13df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 14df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 15df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 16df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 17df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 18df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 19df8bae1dSRodney W. Grimes * must display the following acknowledgement: 20df8bae1dSRodney W. Grimes * This product includes software developed by the University of 21df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 22df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 23df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 24df8bae1dSRodney W. Grimes * without specific prior written permission. 25df8bae1dSRodney W. Grimes * 26df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36df8bae1dSRodney W. Grimes * SUCH DAMAGE. 37df8bae1dSRodney W. Grimes * 38df8bae1dSRodney W. Grimes * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 39c3aac50fSPeter Wemm * $FreeBSD$ 40df8bae1dSRodney W. Grimes */ 41df8bae1dSRodney W. Grimes 425591b823SEivind Eklund #include "opt_compat.h" 43db6a20e2SGarrett Wollman #include "opt_ktrace.h" 442555374cSRobert Watson #include "opt_mac.h" 45db6a20e2SGarrett Wollman 46df8bae1dSRodney W. Grimes #include <sys/param.h> 47df8bae1dSRodney W. Grimes #include <sys/systm.h> 485fdb8324SBruce Evans #include <sys/sysproto.h> 491c5bb3eaSPeter Wemm #include <sys/kernel.h> 50a1c995b6SPoul-Henning Kamp #include <sys/malloc.h> 51f34fa851SJohn Baldwin #include <sys/lock.h> 5235e0e5b3SJohn Baldwin #include <sys/mutex.h> 53df8bae1dSRodney W. Grimes #include <sys/proc.h> 542a024a2bSSean Eric Fagan #include <sys/pioctl.h> 55df8bae1dSRodney W. Grimes #include <sys/tty.h> 56df8bae1dSRodney W. Grimes #include <sys/wait.h> 57eb30c1c0SPeter Wemm #include <sys/vmmeter.h> 587a6b989bSJohn Baldwin #include <sys/vnode.h> 59df8bae1dSRodney W. Grimes #include <sys/resourcevar.h> 60797f2d22SPoul-Henning Kamp #include <sys/signalvar.h> 61b43179fbSJeff Roberson #include <sys/sched.h> 621005a129SJohn Baldwin #include <sys/sx.h> 63df8bae1dSRodney W. Grimes #include <sys/ptrace.h> 647c409b8aSJeffrey Hsu #include <sys/acct.h> /* for acct_process() function prototype */ 65797f2d22SPoul-Henning Kamp #include <sys/filedesc.h> 662555374cSRobert Watson #include <sys/mac.h> 67780dc5a8SPeter Wemm #include <sys/shm.h> 68780dc5a8SPeter Wemm #include <sys/sem.h> 6975c13541SPoul-Henning Kamp #include <sys/jail.h> 706c84de02SJohn Baldwin #ifdef KTRACE 716c84de02SJohn Baldwin #include <sys/ktrace.h> 726c84de02SJohn Baldwin #endif 73780dc5a8SPeter Wemm 74df8bae1dSRodney W. Grimes #include <vm/vm.h> 75eb30c1c0SPeter Wemm #include <vm/vm_extern.h> 767a6b989bSJohn Baldwin #include <vm/vm_param.h> 77efeaf95aSDavid Greenman #include <vm/pmap.h> 78efeaf95aSDavid Greenman #include <vm/vm_map.h> 792d21129dSAlan Cox #include <vm/vm_page.h> 80c897b813SJeff Roberson #include <vm/uma.h> 81dc9c271aSJulian Elischer #include <sys/user.h> 82df8bae1dSRodney W. Grimes 83ba198b1cSMark Newton /* Required to be non-static for SysVR4 emulator */ 8469a6f20bSMark Newton MALLOC_DEFINE(M_ZOMBIE, "zombie", "zombie proc status"); 8555166637SPoul-Henning Kamp 8693efcae8SPoul-Henning Kamp static MALLOC_DEFINE(M_ATEXIT, "atexit", "atexit callback"); 8793efcae8SPoul-Henning Kamp 884d77a549SAlfred Perlstein static int wait1(struct thread *, struct wait_args *, int); 895fdb8324SBruce Evans 90df8bae1dSRodney W. Grimes /* 91fed06968SJulian Elischer * callout list for things to do at exit time 92fed06968SJulian Elischer */ 9393efcae8SPoul-Henning Kamp struct exitlist { 94fed06968SJulian Elischer exitlist_fn function; 95e3975643SJake Burkholder TAILQ_ENTRY(exitlist) next; 9693efcae8SPoul-Henning Kamp }; 97fed06968SJulian Elischer 98e3975643SJake Burkholder TAILQ_HEAD(exit_list_head, exitlist); 9993efcae8SPoul-Henning Kamp static struct exit_list_head exit_list = TAILQ_HEAD_INITIALIZER(exit_list); 100fed06968SJulian Elischer 101fed06968SJulian Elischer /* 102df8bae1dSRodney W. Grimes * exit -- 103df8bae1dSRodney W. Grimes * Death of process. 104234216efSMatthew Dillon * 105234216efSMatthew Dillon * MPSAFE 106df8bae1dSRodney W. Grimes */ 107fc0b1dbfSBruce Evans void 108b40ce416SJulian Elischer sys_exit(td, uap) 109b40ce416SJulian Elischer struct thread *td; 110ac2b067bSPeter Wemm struct sys_exit_args /* { 1115fdb8324SBruce Evans int rval; 1125fdb8324SBruce Evans } */ *uap; 113df8bae1dSRodney W. Grimes { 114b40ce416SJulian Elischer 115234216efSMatthew Dillon mtx_lock(&Giant); 116b40ce416SJulian Elischer exit1(td, W_EXITCODE(uap->rval, 0)); 117df8bae1dSRodney W. Grimes /* NOTREACHED */ 118df8bae1dSRodney W. Grimes } 119df8bae1dSRodney W. Grimes 120df8bae1dSRodney W. Grimes /* 121df8bae1dSRodney W. Grimes * Exit: deallocate address space and other resources, change proc state 122df8bae1dSRodney W. Grimes * to zombie, and unlink proc from allproc and parent's lists. Save exit 123df8bae1dSRodney W. Grimes * status and rusage for wait(). Check for child processes and orphan them. 124df8bae1dSRodney W. Grimes */ 125fc0b1dbfSBruce Evans void 126b40ce416SJulian Elischer exit1(td, rv) 127b40ce416SJulian Elischer register struct thread *td; 128df8bae1dSRodney W. Grimes int rv; 129df8bae1dSRodney W. Grimes { 130276c5169SJohn Baldwin struct exitlist *ep; 131276c5169SJohn Baldwin struct proc *p, *nq, *q; 132276c5169SJohn Baldwin struct tty *tp; 133276c5169SJohn Baldwin struct vnode *ttyvp; 134df8bae1dSRodney W. Grimes register struct vmspace *vm; 13579deba82SMatthew Dillon struct vnode *vtmp; 136d7aadbf9SJohn Baldwin #ifdef KTRACE 137d7aadbf9SJohn Baldwin struct vnode *tracevp; 138a5881ea5SJohn Baldwin struct ucred *tracecred; 139d7aadbf9SJohn Baldwin #endif 140df8bae1dSRodney W. Grimes 1410cddd8f0SMatthew Dillon GIANT_REQUIRED; 1420cddd8f0SMatthew Dillon 143276c5169SJohn Baldwin p = td->td_proc; 144e746d950SJohn Baldwin if (p == initproc) { 1455f7bd355SPoul-Henning Kamp printf("init died (signal %d, exit %d)\n", 146df8bae1dSRodney W. Grimes WTERMSIG(rv), WEXITSTATUS(rv)); 1475f7bd355SPoul-Henning Kamp panic("Going nowhere without my init!"); 1485f7bd355SPoul-Henning Kamp } 1492c1011f7SJohn Dyson 1507a6b989bSJohn Baldwin /* 1515215b187SJeff Roberson * XXXKSE: MUST abort all other threads before proceeding past here. 1527a6b989bSJohn Baldwin */ 153e602ba25SJulian Elischer PROC_LOCK(p); 154ac2e4153SJulian Elischer if (p->p_flag & P_THREADED) { 155e602ba25SJulian Elischer /* 156e602ba25SJulian Elischer * First check if some other thread got here before us.. 157e602ba25SJulian Elischer * if so, act apropriatly, (exit or suspend); 158e602ba25SJulian Elischer */ 159e602ba25SJulian Elischer thread_suspend_check(0); 160e602ba25SJulian Elischer 161e602ba25SJulian Elischer /* 162e602ba25SJulian Elischer * Kill off the other threads. This requires 163e602ba25SJulian Elischer * Some co-operation from other parts of the kernel 164e602ba25SJulian Elischer * so it may not be instant. 165e602ba25SJulian Elischer * With this state set: 166e602ba25SJulian Elischer * Any thread entering the kernel from userspace will 167e602ba25SJulian Elischer * thread_exit() in trap(). Any thread attempting to 168e602ba25SJulian Elischer * sleep will return immediatly 169e602ba25SJulian Elischer * with EINTR or EWOULDBLOCK, which will hopefully force them 170e602ba25SJulian Elischer * to back out to userland, freeing resources as they go, and 171e602ba25SJulian Elischer * anything attempting to return to userland will thread_exit() 172e602ba25SJulian Elischer * from userret(). thread_exit() will unsuspend us 173e602ba25SJulian Elischer * when the last other thread exits. 174e602ba25SJulian Elischer */ 1751279572aSDavid Xu if (thread_single(SINGLE_EXIT)) { 176e602ba25SJulian Elischer panic ("Exit: Single threading fouled up"); 177e602ba25SJulian Elischer } 178e602ba25SJulian Elischer /* 179e602ba25SJulian Elischer * All other activity in this process is now stopped. 180e602ba25SJulian Elischer * Remove excess KSEs and KSEGRPS. XXXKSE (when we have them) 181e602ba25SJulian Elischer * ... 182e602ba25SJulian Elischer * Turn off threading support. 183e602ba25SJulian Elischer */ 184ac2e4153SJulian Elischer p->p_flag &= ~P_THREADED; 185e602ba25SJulian Elischer thread_single_end(); /* Don't need this any more. */ 186e602ba25SJulian Elischer } 187e602ba25SJulian Elischer /* 188e602ba25SJulian Elischer * With this state set: 189e602ba25SJulian Elischer * Any thread entering the kernel from userspace will thread_exit() 190e602ba25SJulian Elischer * in trap(). Any thread attempting to sleep will return immediatly 191e602ba25SJulian Elischer * with EINTR or EWOULDBLOCK, which will hopefully force them 192e602ba25SJulian Elischer * to back out to userland, freeing resources as they go, and 193e602ba25SJulian Elischer * anything attempting to return to userland will thread_exit() 194e602ba25SJulian Elischer * from userret(). thread_exit() will do a wakeup on p->p_numthreads 195e602ba25SJulian Elischer * if it transitions to 1. 196e602ba25SJulian Elischer */ 197e602ba25SJulian Elischer 198e602ba25SJulian Elischer p->p_flag |= P_WEXIT; 199e602ba25SJulian Elischer PROC_UNLOCK(p); 200b40ce416SJulian Elischer 2017a6b989bSJohn Baldwin /* Are we a task leader? */ 2022c1011f7SJohn Dyson if (p == p->p_leader) { 203c6544064SJohn Baldwin mtx_lock(&ppeers_lock); 2042c1011f7SJohn Dyson q = p->p_peers; 205776e0b36SJohn Baldwin while (q != NULL) { 206776e0b36SJohn Baldwin PROC_LOCK(q); 207776e0b36SJohn Baldwin psignal(q, SIGKILL); 208776e0b36SJohn Baldwin PROC_UNLOCK(q); 2092c1011f7SJohn Dyson q = q->p_peers; 2102c1011f7SJohn Dyson } 211c6544064SJohn Baldwin while (p->p_peers != NULL) 212c6544064SJohn Baldwin msleep(p, &ppeers_lock, PWAIT, "exit1", 0); 213c6544064SJohn Baldwin mtx_unlock(&ppeers_lock); 2142c1011f7SJohn Dyson } 2152c1011f7SJohn Dyson 216df8bae1dSRodney W. Grimes #ifdef PGINPROF 217df8bae1dSRodney W. Grimes vmsizmon(); 218df8bae1dSRodney W. Grimes #endif 2192a024a2bSSean Eric Fagan STOPEVENT(p, S_EXIT, rv); 22089361835SSean Eric Fagan wakeup(&p->p_stype); /* Wakeup anyone in procfs' PIOCWAIT */ 2212a024a2bSSean Eric Fagan 222fed06968SJulian Elischer /* 223e9189611SPeter Wemm * Check if any loadable modules need anything done at process exit. 224fed06968SJulian Elischer * e.g. SYSV IPC stuff 225fed06968SJulian Elischer * XXX what if one of these generates an error? 226fed06968SJulian Elischer */ 22793efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &exit_list, next) 228fed06968SJulian Elischer (*ep->function)(p); 229fed06968SJulian Elischer 230a914fb6bSJohn Baldwin 231df8bae1dSRodney W. Grimes MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 232a163d034SWarner Losh M_ZOMBIE, M_WAITOK); 233df8bae1dSRodney W. Grimes /* 234df8bae1dSRodney W. Grimes * If parent is waiting for us to exit or exec, 235df8bae1dSRodney W. Grimes * P_PPWAIT is set; we will wakeup the parent below. 236df8bae1dSRodney W. Grimes */ 237a914fb6bSJohn Baldwin PROC_LOCK(p); 238a282253aSJulian Elischer stopprofclock(p); 239df8bae1dSRodney W. Grimes p->p_flag &= ~(P_TRACED | P_PPWAIT); 2401d9c5696SJuli Mallett SIGEMPTYSET(p->p_siglist); 2414cf41af3SPoul-Henning Kamp if (timevalisset(&p->p_realtimer.it_value)) 2424f559836SJake Burkholder callout_stop(&p->p_itcallout); 24396d7f8efSTim J. Robbins PROC_UNLOCK(p); 244df8bae1dSRodney W. Grimes 245df8bae1dSRodney W. Grimes /* 246831d27a9SDon Lewis * Reset any sigio structures pointing to us as a result of 247831d27a9SDon Lewis * F_SETOWN with our pid. 248831d27a9SDon Lewis */ 249831d27a9SDon Lewis funsetownlst(&p->p_sigiolst); 250831d27a9SDon Lewis 251831d27a9SDon Lewis /* 252df8bae1dSRodney W. Grimes * Close open files and release open-file table. 253df8bae1dSRodney W. Grimes * This may block! 254df8bae1dSRodney W. Grimes */ 255edf6699aSAlfred Perlstein fdfree(td); 256df8bae1dSRodney W. Grimes 257a914fb6bSJohn Baldwin /* 258a914fb6bSJohn Baldwin * Remove ourself from our leader's peer list and wake our leader. 259a914fb6bSJohn Baldwin */ 260c6544064SJohn Baldwin mtx_lock(&ppeers_lock); 26179fc0bf4SMike Smith if (p->p_leader->p_peers) { 26279fc0bf4SMike Smith q = p->p_leader; 26379fc0bf4SMike Smith while (q->p_peers != p) 26479fc0bf4SMike Smith q = q->p_peers; 26579fc0bf4SMike Smith q->p_peers = p->p_peers; 2667f05b035SAlfred Perlstein wakeup(p->p_leader); 26779fc0bf4SMike Smith } 268c6544064SJohn Baldwin mtx_unlock(&ppeers_lock); 26979fc0bf4SMike Smith 270df8bae1dSRodney W. Grimes /* The next two chunks should probably be moved to vmspace_exit. */ 271df8bae1dSRodney W. Grimes vm = p->p_vmspace; 272df8bae1dSRodney W. Grimes /* 273df8bae1dSRodney W. Grimes * Release user portion of address space. 274df8bae1dSRodney W. Grimes * This releases references to vnodes, 275df8bae1dSRodney W. Grimes * which could cause I/O if the file has been unlinked. 276df8bae1dSRodney W. Grimes * Need to do this early enough that we can still sleep. 277df8bae1dSRodney W. Grimes * Can't free the entire vmspace as the kernel stack 278df8bae1dSRodney W. Grimes * may be mapped within that space also. 279389d2b6eSMatthew Dillon * 280389d2b6eSMatthew Dillon * Processes sharing the same vmspace may exit in one order, and 281389d2b6eSMatthew Dillon * get cleaned up by vmspace_exit() in a different order. The 282389d2b6eSMatthew Dillon * last exiting process to reach this point releases as much of 283389d2b6eSMatthew Dillon * the environment as it can, and the last process cleaned up 284389d2b6eSMatthew Dillon * by vmspace_exit() (which decrements exitingcnt) cleans up the 285389d2b6eSMatthew Dillon * remainder. 286df8bae1dSRodney W. Grimes */ 287389d2b6eSMatthew Dillon ++vm->vm_exitingcnt; 288582ec34cSAlfred Perlstein if (--vm->vm_refcnt == 0) { 2893db161e0SMatthew Dillon shmexit(vm); 2902d21129dSAlan Cox vm_page_lock_queues(); 29105ba50f5SJake Burkholder pmap_remove_pages(vmspace_pmap(vm), vm_map_min(&vm->vm_map), 29205ba50f5SJake Burkholder vm_map_max(&vm->vm_map)); 2932d21129dSAlan Cox vm_page_unlock_queues(); 29405ba50f5SJake Burkholder (void) vm_map_remove(&vm->vm_map, vm_map_min(&vm->vm_map), 29505ba50f5SJake Burkholder vm_map_max(&vm->vm_map)); 2969d3fbbb5SJohn Dyson } 297df8bae1dSRodney W. Grimes 298ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 299df8bae1dSRodney W. Grimes if (SESS_LEADER(p)) { 300f591779bSSeigo Tanimura register struct session *sp; 301df8bae1dSRodney W. Grimes 302f591779bSSeigo Tanimura sp = p->p_session; 303df8bae1dSRodney W. Grimes if (sp->s_ttyvp) { 304df8bae1dSRodney W. Grimes /* 305df8bae1dSRodney W. Grimes * Controlling process. 306df8bae1dSRodney W. Grimes * Signal foreground pgrp, 307df8bae1dSRodney W. Grimes * drain controlling terminal 308df8bae1dSRodney W. Grimes * and revoke access to controlling terminal. 309df8bae1dSRodney W. Grimes */ 310dd45d8adSJulian Elischer if (sp->s_ttyp && (sp->s_ttyp->t_session == sp)) { 311f591779bSSeigo Tanimura tp = sp->s_ttyp; 312f591779bSSeigo Tanimura if (sp->s_ttyp->t_pgrp) { 313f591779bSSeigo Tanimura PGRP_LOCK(sp->s_ttyp->t_pgrp); 314df8bae1dSRodney W. Grimes pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 315f591779bSSeigo Tanimura PGRP_UNLOCK(sp->s_ttyp->t_pgrp); 316f591779bSSeigo Tanimura } 317f591779bSSeigo Tanimura /* XXX tp should be locked. */ 318ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 319f591779bSSeigo Tanimura (void) ttywait(tp); 320ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 321df8bae1dSRodney W. Grimes /* 322df8bae1dSRodney W. Grimes * The tty could have been revoked 323df8bae1dSRodney W. Grimes * if we blocked. 324df8bae1dSRodney W. Grimes */ 325f591779bSSeigo Tanimura if (sp->s_ttyvp) { 326f591779bSSeigo Tanimura ttyvp = sp->s_ttyvp; 327f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 328df8bae1dSRodney W. Grimes sp->s_ttyvp = NULL; 329f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 330ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 331f591779bSSeigo Tanimura VOP_REVOKE(ttyvp, REVOKEALL); 332f591779bSSeigo Tanimura vrele(ttyvp); 333ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 334f591779bSSeigo Tanimura } 335f591779bSSeigo Tanimura } 336f591779bSSeigo Tanimura if (sp->s_ttyvp) { 337f591779bSSeigo Tanimura ttyvp = sp->s_ttyvp; 338f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 339f591779bSSeigo Tanimura sp->s_ttyvp = NULL; 340f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 341f591779bSSeigo Tanimura vrele(ttyvp); 342f591779bSSeigo Tanimura } 343df8bae1dSRodney W. Grimes /* 344df8bae1dSRodney W. Grimes * s_ttyp is not zero'd; we use this to indicate 345df8bae1dSRodney W. Grimes * that the session once had a controlling terminal. 346df8bae1dSRodney W. Grimes * (for logging and informational purposes) 347df8bae1dSRodney W. Grimes */ 348df8bae1dSRodney W. Grimes } 349f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 350df8bae1dSRodney W. Grimes sp->s_leader = NULL; 351f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 352f591779bSSeigo Tanimura } 353df8bae1dSRodney W. Grimes fixjobc(p, p->p_pgrp, 0); 354ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 355b40ce416SJulian Elischer (void)acct_process(td); 356df8bae1dSRodney W. Grimes #ifdef KTRACE 357df8bae1dSRodney W. Grimes /* 358df8bae1dSRodney W. Grimes * release trace file 359df8bae1dSRodney W. Grimes */ 360d7aadbf9SJohn Baldwin PROC_LOCK(p); 3616c84de02SJohn Baldwin mtx_lock(&ktrace_mtx); 362df8bae1dSRodney W. Grimes p->p_traceflag = 0; /* don't trace the vrele() */ 363a5881ea5SJohn Baldwin tracevp = p->p_tracevp; 364a5881ea5SJohn Baldwin p->p_tracevp = NULL; 365a5881ea5SJohn Baldwin tracecred = p->p_tracecred; 366a5881ea5SJohn Baldwin p->p_tracecred = NULL; 3676c84de02SJohn Baldwin mtx_unlock(&ktrace_mtx); 368d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 369d7aadbf9SJohn Baldwin if (tracevp != NULL) 370d7aadbf9SJohn Baldwin vrele(tracevp); 371a5881ea5SJohn Baldwin if (tracecred != NULL) 372a5881ea5SJohn Baldwin crfree(tracecred); 373df8bae1dSRodney W. Grimes #endif 374df8bae1dSRodney W. Grimes /* 375ee42d0a9SDavid Malone * Release reference to text vnode 376ee42d0a9SDavid Malone */ 377ee42d0a9SDavid Malone if ((vtmp = p->p_textvp) != NULL) { 378ee42d0a9SDavid Malone p->p_textvp = NULL; 379ee42d0a9SDavid Malone vrele(vtmp); 380ee42d0a9SDavid Malone } 381ee42d0a9SDavid Malone 382ee42d0a9SDavid Malone /* 383d7aadbf9SJohn Baldwin * Release our limits structure. 384d7aadbf9SJohn Baldwin */ 385d7aadbf9SJohn Baldwin mtx_assert(&Giant, MA_OWNED); 386d7aadbf9SJohn Baldwin if (--p->p_limit->p_refcnt == 0) { 387d7aadbf9SJohn Baldwin FREE(p->p_limit, M_SUBPROC); 388d7aadbf9SJohn Baldwin p->p_limit = NULL; 389d7aadbf9SJohn Baldwin } 390d7aadbf9SJohn Baldwin 391d7aadbf9SJohn Baldwin /* 392d7aadbf9SJohn Baldwin * Release this thread's reference to the ucred. The actual proc 393d7aadbf9SJohn Baldwin * reference will stay around until the proc is harvested by 394d7aadbf9SJohn Baldwin * wait(). At this point the ucred is immutable (no other threads 395d7aadbf9SJohn Baldwin * from this proc are around that can change it) so we leave the 396d7aadbf9SJohn Baldwin * per-thread ucred pointer intact in case it is needed although 397d7aadbf9SJohn Baldwin * in theory nothing should be using it at this point. 398d7aadbf9SJohn Baldwin */ 399d7aadbf9SJohn Baldwin crfree(td->td_ucred); 400d7aadbf9SJohn Baldwin 401d7aadbf9SJohn Baldwin /* 402df8bae1dSRodney W. Grimes * Remove proc from allproc queue and pidhash chain. 403df8bae1dSRodney W. Grimes * Place onto zombproc. Unlink from parent's child list. 404df8bae1dSRodney W. Grimes */ 4051005a129SJohn Baldwin sx_xlock(&allproc_lock); 406b75356e1SJeffrey Hsu LIST_REMOVE(p, p_list); 407b75356e1SJeffrey Hsu LIST_INSERT_HEAD(&zombproc, p, p_list); 408b75356e1SJeffrey Hsu LIST_REMOVE(p, p_hash); 4091005a129SJohn Baldwin sx_xunlock(&allproc_lock); 410df8bae1dSRodney W. Grimes 4111005a129SJohn Baldwin sx_xlock(&proctree_lock); 4122e3c8fcbSPoul-Henning Kamp q = LIST_FIRST(&p->p_children); 413a914fb6bSJohn Baldwin if (q != NULL) /* only need this if any child is S_ZOMB */ 4147f05b035SAlfred Perlstein wakeup(initproc); 415a914fb6bSJohn Baldwin for (; q != NULL; q = nq) { 4162e3c8fcbSPoul-Henning Kamp nq = LIST_NEXT(q, p_sibling); 417a914fb6bSJohn Baldwin PROC_LOCK(q); 418c65437a3SJohn Baldwin proc_reparent(q, initproc); 4194ac9ae70SJulian Elischer q->p_sigparent = SIGCHLD; 420df8bae1dSRodney W. Grimes /* 421df8bae1dSRodney W. Grimes * Traced processes are killed 422df8bae1dSRodney W. Grimes * since their existence means someone is screwing up. 423df8bae1dSRodney W. Grimes */ 424df8bae1dSRodney W. Grimes if (q->p_flag & P_TRACED) { 425df8bae1dSRodney W. Grimes q->p_flag &= ~P_TRACED; 426df8bae1dSRodney W. Grimes psignal(q, SIGKILL); 427c65437a3SJohn Baldwin } 428a914fb6bSJohn Baldwin PROC_UNLOCK(q); 429df8bae1dSRodney W. Grimes } 430df8bae1dSRodney W. Grimes 431df8bae1dSRodney W. Grimes /* 432df8bae1dSRodney W. Grimes * Save exit status and final rusage info, adding in child rusage 433df8bae1dSRodney W. Grimes * info and self times. 434df8bae1dSRodney W. Grimes */ 435d7aadbf9SJohn Baldwin PROC_LOCK(p); 436df8bae1dSRodney W. Grimes p->p_xstat = rv; 437df8bae1dSRodney W. Grimes *p->p_ru = p->p_stats->p_ru; 4389ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 439df8bae1dSRodney W. Grimes calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL); 4409ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 441df8bae1dSRodney W. Grimes ruadd(p->p_ru, &p->p_stats->p_cru); 442df8bae1dSRodney W. Grimes 443df8bae1dSRodney W. Grimes /* 4447a6b989bSJohn Baldwin * Notify interested parties of our demise. 445cb679c38SJonathan Lemon */ 446a274d19bSBrian Feldman KNOTE(&p->p_klist, NOTE_EXIT); 447cb679c38SJonathan Lemon 448cb679c38SJonathan Lemon /* 449645682fdSLuoqi Chen * Notify parent that we're gone. If parent has the PS_NOCLDWAIT 450ba1551caSIan Dowse * flag set, or if the handler is set to SIG_IGN, notify process 451ba1551caSIan Dowse * 1 instead (and hope it will handle this situation). 452df8bae1dSRodney W. Grimes */ 453d7aadbf9SJohn Baldwin PROC_LOCK(p->p_pptr); 454ba1551caSIan Dowse if (p->p_pptr->p_procsig->ps_flag & (PS_NOCLDWAIT | PS_CLDSIGIGN)) { 455276c5169SJohn Baldwin struct proc *pp; 456276c5169SJohn Baldwin 457276c5169SJohn Baldwin pp = p->p_pptr; 458f591779bSSeigo Tanimura PROC_UNLOCK(pp); 459245f17d4SJoerg Wunsch proc_reparent(p, initproc); 460f591779bSSeigo Tanimura PROC_LOCK(p->p_pptr); 461245f17d4SJoerg Wunsch /* 462245f17d4SJoerg Wunsch * If this was the last child of our parent, notify 463245f17d4SJoerg Wunsch * parent, so in case he was wait(2)ing, he will 464245f17d4SJoerg Wunsch * continue. 465245f17d4SJoerg Wunsch */ 466245f17d4SJoerg Wunsch if (LIST_EMPTY(&pp->p_children)) 4677f05b035SAlfred Perlstein wakeup(pp); 468245f17d4SJoerg Wunsch } 469245f17d4SJoerg Wunsch 470c65437a3SJohn Baldwin if (p->p_sigparent && p->p_pptr != initproc) 4716626c604SJulian Elischer psignal(p->p_pptr, p->p_sigparent); 472c65437a3SJohn Baldwin else 4736626c604SJulian Elischer psignal(p->p_pptr, SIGCHLD); 474c65437a3SJohn Baldwin PROC_UNLOCK(p->p_pptr); 475776e0b36SJohn Baldwin 476776e0b36SJohn Baldwin /* 477776e0b36SJohn Baldwin * If this is a kthread, then wakeup anyone waiting for it to exit. 478776e0b36SJohn Baldwin */ 479776e0b36SJohn Baldwin if (p->p_flag & P_KTHREAD) 4807f05b035SAlfred Perlstein wakeup(p); 481c65437a3SJohn Baldwin PROC_UNLOCK(p); 4828e2e767bSJohn Baldwin 4838e2e767bSJohn Baldwin /* 484df8bae1dSRodney W. Grimes * Finally, call machine-dependent code to release the remaining 485696058c3SJulian Elischer * resources including address space. 486582ec34cSAlfred Perlstein * The address space is released by "vmspace_exitfree(p)" in 487582ec34cSAlfred Perlstein * vm_waitproc(). 488df8bae1dSRodney W. Grimes */ 489b40ce416SJulian Elischer cpu_exit(td); 490eb30c1c0SPeter Wemm 491eb30c1c0SPeter Wemm PROC_LOCK(p); 492d7aadbf9SJohn Baldwin PROC_LOCK(p->p_pptr); 493d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 494eb30c1c0SPeter Wemm mtx_lock_spin(&sched_lock); 495696058c3SJulian Elischer 496eb30c1c0SPeter Wemm while (mtx_owned(&Giant)) 497c86b6ff5SJohn Baldwin mtx_unlock(&Giant); 498eb30c1c0SPeter Wemm 499eb30c1c0SPeter Wemm /* 500eb30c1c0SPeter Wemm * We have to wait until after releasing all locks before 501e602ba25SJulian Elischer * changing p_state. If we block on a mutex then we will be 502eb30c1c0SPeter Wemm * back at SRUN when we resume and our parent will never 503eb30c1c0SPeter Wemm * harvest us. 504eb30c1c0SPeter Wemm */ 505e602ba25SJulian Elischer p->p_state = PRS_ZOMBIE; 506eb30c1c0SPeter Wemm 507eb30c1c0SPeter Wemm wakeup(p->p_pptr); 508d7aadbf9SJohn Baldwin PROC_UNLOCK(p->p_pptr); 509eb30c1c0SPeter Wemm cnt.v_swtch++; 510d7aadbf9SJohn Baldwin binuptime(PCPU_PTR(switchtime)); 511d7aadbf9SJohn Baldwin PCPU_SET(switchticks, ticks); 512d7aadbf9SJohn Baldwin 513e602ba25SJulian Elischer cpu_sched_exit(td); /* XXXKSE check if this should be in thread_exit */ 514e602ba25SJulian Elischer /* 515696058c3SJulian Elischer * Make sure the scheduler takes this thread out of its tables etc. 516e602ba25SJulian Elischer * This will also release this thread's reference to the ucred. 517696058c3SJulian Elischer * Other thread parts to release include pcb bits and such. 518e602ba25SJulian Elischer */ 519e602ba25SJulian Elischer thread_exit(); 520df8bae1dSRodney W. Grimes } 521df8bae1dSRodney W. Grimes 522b2f9e8b1SBruce Evans #ifdef COMPAT_43 523234216efSMatthew Dillon /* 5247a6b989bSJohn Baldwin * MPSAFE. The dirty work is handled by wait1(). 525234216efSMatthew Dillon */ 52626f9a767SRodney W. Grimes int 527b40ce416SJulian Elischer owait(td, uap) 528b40ce416SJulian Elischer struct thread *td; 5295fdb8324SBruce Evans register struct owait_args /* { 5305fdb8324SBruce Evans int dummy; 5315fdb8324SBruce Evans } */ *uap; 532df8bae1dSRodney W. Grimes { 53393c9414eSSteven Wallace struct wait_args w; 534df8bae1dSRodney W. Grimes 53593c9414eSSteven Wallace w.options = 0; 53693c9414eSSteven Wallace w.rusage = NULL; 53793c9414eSSteven Wallace w.pid = WAIT_ANY; 53893c9414eSSteven Wallace w.status = NULL; 539b40ce416SJulian Elischer return (wait1(td, &w, 1)); 540df8bae1dSRodney W. Grimes } 541b2f9e8b1SBruce Evans #endif /* COMPAT_43 */ 542df8bae1dSRodney W. Grimes 543234216efSMatthew Dillon /* 5447a6b989bSJohn Baldwin * MPSAFE. The dirty work is handled by wait1(). 545234216efSMatthew Dillon */ 54626f9a767SRodney W. Grimes int 547b40ce416SJulian Elischer wait4(td, uap) 548b40ce416SJulian Elischer struct thread *td; 549df8bae1dSRodney W. Grimes struct wait_args *uap; 550df8bae1dSRodney W. Grimes { 551b40ce416SJulian Elischer 552b40ce416SJulian Elischer return (wait1(td, uap, 0)); 553df8bae1dSRodney W. Grimes } 554df8bae1dSRodney W. Grimes 555234216efSMatthew Dillon /* 556234216efSMatthew Dillon * MPSAFE 557234216efSMatthew Dillon */ 55893c9414eSSteven Wallace static int 559b40ce416SJulian Elischer wait1(td, uap, compat) 560b40ce416SJulian Elischer register struct thread *td; 5615fdb8324SBruce Evans register struct wait_args /* { 5625fdb8324SBruce Evans int pid; 5635fdb8324SBruce Evans int *status; 5645fdb8324SBruce Evans int options; 5655fdb8324SBruce Evans struct rusage *rusage; 5665fdb8324SBruce Evans } */ *uap; 56793c9414eSSteven Wallace int compat; 568df8bae1dSRodney W. Grimes { 569276c5169SJohn Baldwin struct rusage ru; 57048bfcdddSJulian Elischer int nfound; 57148bfcdddSJulian Elischer struct proc *p, *q, *t; 572f23c6d68SSteven Wallace int status, error; 573df8bae1dSRodney W. Grimes 574b40ce416SJulian Elischer q = td->td_proc; 575f591779bSSeigo Tanimura if (uap->pid == 0) { 576f591779bSSeigo Tanimura PROC_LOCK(q); 577df8bae1dSRodney W. Grimes uap->pid = -q->p_pgid; 578f591779bSSeigo Tanimura PROC_UNLOCK(q); 579f591779bSSeigo Tanimura } 5806ee093fbSMike Barcroft if (uap->options &~ (WUNTRACED|WNOHANG|WCONTINUED|WLINUXCLONE)) 5816dc958b9SJohn Baldwin return (EINVAL); 5826dc958b9SJohn Baldwin mtx_lock(&Giant); 583df8bae1dSRodney W. Grimes loop: 584df8bae1dSRodney W. Grimes nfound = 0; 585d7aadbf9SJohn Baldwin sx_xlock(&proctree_lock); 5862e3c8fcbSPoul-Henning Kamp LIST_FOREACH(p, &q->p_children, p_sibling) { 587f591779bSSeigo Tanimura PROC_LOCK(p); 588df8bae1dSRodney W. Grimes if (uap->pid != WAIT_ANY && 589f591779bSSeigo Tanimura p->p_pid != uap->pid && p->p_pgid != -uap->pid) { 590f591779bSSeigo Tanimura PROC_UNLOCK(p); 591df8bae1dSRodney W. Grimes continue; 592f591779bSSeigo Tanimura } 5934ac9ae70SJulian Elischer 5941156bc4dSJake Burkholder /* 5951156bc4dSJake Burkholder * This special case handles a kthread spawned by linux_clone 5961156bc4dSJake Burkholder * (see linux_misc.c). The linux_wait4 and linux_waitpid 5971156bc4dSJake Burkholder * functions need to be able to distinguish between waiting 5981156bc4dSJake Burkholder * on a process and waiting on a thread. It is a thread if 5991156bc4dSJake Burkholder * p_sigparent is not SIGCHLD, and the WLINUXCLONE option 6001156bc4dSJake Burkholder * signifies we want to wait for threads and not processes. 6014ac9ae70SJulian Elischer */ 6021156bc4dSJake Burkholder if ((p->p_sigparent != SIGCHLD) ^ 603a914fb6bSJohn Baldwin ((uap->options & WLINUXCLONE) != 0)) { 604a914fb6bSJohn Baldwin PROC_UNLOCK(p); 6054ac9ae70SJulian Elischer continue; 606a914fb6bSJohn Baldwin } 6074ac9ae70SJulian Elischer 608df8bae1dSRodney W. Grimes nfound++; 609e602ba25SJulian Elischer if (p->p_state == PRS_ZOMBIE) { 610b40ce416SJulian Elischer /* 611b43179fbSJeff Roberson * Allow the scheduler to adjust the priority of the 612b43179fbSJeff Roberson * parent when a kseg is exiting. 613b40ce416SJulian Elischer */ 614b40ce416SJulian Elischer if (curthread->td_proc->p_pid != 1) { 615d7aadbf9SJohn Baldwin mtx_lock_spin(&sched_lock); 616b43179fbSJeff Roberson sched_exit(curthread->td_ksegrp, 617b43179fbSJeff Roberson FIRST_KSEGRP_IN_PROC(p)); 618c65437a3SJohn Baldwin mtx_unlock_spin(&sched_lock); 619d7aadbf9SJohn Baldwin } 620c65437a3SJohn Baldwin 621b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 622b2f9e8b1SBruce Evans #ifdef COMPAT_43 62393c9414eSSteven Wallace if (compat) 624b40ce416SJulian Elischer td->td_retval[1] = p->p_xstat; 625df8bae1dSRodney W. Grimes else 626df8bae1dSRodney W. Grimes #endif 627df8bae1dSRodney W. Grimes if (uap->status) { 628df8bae1dSRodney W. Grimes status = p->p_xstat; /* convert to int */ 629d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 6307f05b035SAlfred Perlstein if ((error = copyout(&status, 6317f05b035SAlfred Perlstein uap->status, sizeof(status)))) { 632d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 633d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 634d7aadbf9SJohn Baldwin return (error); 635234216efSMatthew Dillon } 636d7aadbf9SJohn Baldwin PROC_LOCK(p); 637df8bae1dSRodney W. Grimes } 638d7aadbf9SJohn Baldwin if (uap->rusage) { 639d7aadbf9SJohn Baldwin bcopy(p->p_ru, &ru, sizeof(ru)); 640d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 6417f05b035SAlfred Perlstein if ((error = copyout(&ru, 6427f05b035SAlfred Perlstein uap->rusage, sizeof (struct rusage)))) { 643d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 644d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 645d7aadbf9SJohn Baldwin return (error); 646234216efSMatthew Dillon } 647d7aadbf9SJohn Baldwin } else 648d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 649df8bae1dSRodney W. Grimes /* 650df8bae1dSRodney W. Grimes * If we got the child via a ptrace 'attach', 651df8bae1dSRodney W. Grimes * we need to give it back to the old parent. 652df8bae1dSRodney W. Grimes */ 653d7aadbf9SJohn Baldwin if (p->p_oppid && (t = pfind(p->p_oppid)) != NULL) { 654c65437a3SJohn Baldwin PROC_LOCK(p); 655df8bae1dSRodney W. Grimes p->p_oppid = 0; 656df8bae1dSRodney W. Grimes proc_reparent(p, t); 657c65437a3SJohn Baldwin PROC_UNLOCK(p); 658df8bae1dSRodney W. Grimes psignal(t, SIGCHLD); 6597f05b035SAlfred Perlstein wakeup(t); 660c65437a3SJohn Baldwin PROC_UNLOCK(t); 6611005a129SJohn Baldwin sx_xunlock(&proctree_lock); 662d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 663d7aadbf9SJohn Baldwin return (0); 664df8bae1dSRodney W. Grimes } 665ebdc3f1dSSeigo Tanimura 6663890793eSTim J. Robbins /* 6673890793eSTim J. Robbins * Remove other references to this process to ensure 6683890793eSTim J. Robbins * we have an exclusive reference. 6693890793eSTim J. Robbins */ 6706ec62361STim J. Robbins sx_xlock(&allproc_lock); 6716ec62361STim J. Robbins LIST_REMOVE(p, p_list); /* off zombproc */ 6726ec62361STim J. Robbins sx_xunlock(&allproc_lock); 6736ec62361STim J. Robbins LIST_REMOVE(p, p_sibling); 6743890793eSTim J. Robbins leavepgrp(p); 675ebdc3f1dSSeigo Tanimura sx_xunlock(&proctree_lock); 676ebdc3f1dSSeigo Tanimura 677ebdc3f1dSSeigo Tanimura /* 678d7aadbf9SJohn Baldwin * As a side effect of this lock, we know that 679d7aadbf9SJohn Baldwin * all other writes to this proc are visible now, so 680d7aadbf9SJohn Baldwin * no more locking is needed for p. 681d7aadbf9SJohn Baldwin */ 682d7aadbf9SJohn Baldwin PROC_LOCK(p); 683d7aadbf9SJohn Baldwin p->p_xstat = 0; /* XXX: why? */ 684d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 685d7aadbf9SJohn Baldwin PROC_LOCK(q); 686d7aadbf9SJohn Baldwin ruadd(&q->p_stats->p_cru, p->p_ru); 687d7aadbf9SJohn Baldwin PROC_UNLOCK(q); 688d7aadbf9SJohn Baldwin FREE(p->p_ru, M_ZOMBIE); 689d7aadbf9SJohn Baldwin p->p_ru = NULL; 690d7aadbf9SJohn Baldwin 691d7aadbf9SJohn Baldwin /* 692d7aadbf9SJohn Baldwin * Decrement the count of procs running with this uid. 693d7aadbf9SJohn Baldwin */ 694d7aadbf9SJohn Baldwin (void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0); 695d7aadbf9SJohn Baldwin 696d7aadbf9SJohn Baldwin /* 697df8bae1dSRodney W. Grimes * Free up credentials. 698df8bae1dSRodney W. Grimes */ 699da654d90SPoul-Henning Kamp crfree(p->p_ucred); 700d7aadbf9SJohn Baldwin p->p_ucred = NULL; /* XXX: why? */ 701df8bae1dSRodney W. Grimes 702df8bae1dSRodney W. Grimes /* 703b9df5231SPoul-Henning Kamp * Remove unused arguments 704b9df5231SPoul-Henning Kamp */ 705d7aadbf9SJohn Baldwin pargs_drop(p->p_args); 706d7aadbf9SJohn Baldwin p->p_args = NULL; 707b9df5231SPoul-Henning Kamp 7086626c604SJulian Elischer if (--p->p_procsig->ps_refcnt == 0) { 709b40ce416SJulian Elischer if (p->p_sigacts != &p->p_uarea->u_sigacts) 710dc9c271aSJulian Elischer FREE(p->p_sigacts, M_SUBPROC); 711dc9c271aSJulian Elischer FREE(p->p_procsig, M_SUBPROC); 7126626c604SJulian Elischer p->p_procsig = NULL; 7136626c604SJulian Elischer } 71488c5ea45SJulian Elischer 715df8bae1dSRodney W. Grimes /* 716696058c3SJulian Elischer * do any thread-system specific cleanups 717e602ba25SJulian Elischer */ 718696058c3SJulian Elischer thread_wait(p); 719e602ba25SJulian Elischer 720e602ba25SJulian Elischer /* 721eb30c1c0SPeter Wemm * Give vm and machine-dependent layer a chance 722df8bae1dSRodney W. Grimes * to free anything that cpu_exit couldn't 723df8bae1dSRodney W. Grimes * release while still running in process context. 724df8bae1dSRodney W. Grimes */ 725eb30c1c0SPeter Wemm vm_waitproc(p); 7264971f62aSJohn Baldwin mtx_destroy(&p->p_mtx); 7272555374cSRobert Watson #ifdef MAC 7282555374cSRobert Watson mac_destroy_proc(p); 7292555374cSRobert Watson #endif 7301faf202eSJulian Elischer KASSERT(FIRST_THREAD_IN_PROC(p), 7311faf202eSJulian Elischer ("wait1: no residual thread!")); 732c897b813SJeff Roberson uma_zfree(proc_zone, p); 733d7aadbf9SJohn Baldwin sx_xlock(&allproc_lock); 734df8bae1dSRodney W. Grimes nprocs--; 735d7aadbf9SJohn Baldwin sx_xunlock(&allproc_lock); 736d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 737d7aadbf9SJohn Baldwin return (0); 738df8bae1dSRodney W. Grimes } 739e574e444SDavid Xu if (P_SHOULDSTOP(p) && (p->p_suspcount == p->p_numthreads) && 740e574e444SDavid Xu ((p->p_flag & P_WAITED) == 0) && 741df8bae1dSRodney W. Grimes (p->p_flag & P_TRACED || uap->options & WUNTRACED)) { 742df8bae1dSRodney W. Grimes p->p_flag |= P_WAITED; 743d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 744b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 745b2f9e8b1SBruce Evans #ifdef COMPAT_43 74693c9414eSSteven Wallace if (compat) { 747b40ce416SJulian Elischer td->td_retval[1] = W_STOPCODE(p->p_xstat); 748d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 749df8bae1dSRodney W. Grimes error = 0; 750df8bae1dSRodney W. Grimes } else 751df8bae1dSRodney W. Grimes #endif 752df8bae1dSRodney W. Grimes if (uap->status) { 753df8bae1dSRodney W. Grimes status = W_STOPCODE(p->p_xstat); 754d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 7557f05b035SAlfred Perlstein error = copyout(&status, 7567f05b035SAlfred Perlstein uap->status, sizeof(status)); 757d7aadbf9SJohn Baldwin } else { 758a914fb6bSJohn Baldwin PROC_UNLOCK(p); 759234216efSMatthew Dillon error = 0; 760df8bae1dSRodney W. Grimes } 761234216efSMatthew Dillon mtx_unlock(&Giant); 762234216efSMatthew Dillon return (error); 763df8bae1dSRodney W. Grimes } 7646ee093fbSMike Barcroft if (uap->options & WCONTINUED && (p->p_flag & P_CONTINUED)) { 7656ee093fbSMike Barcroft sx_xunlock(&proctree_lock); 7666ee093fbSMike Barcroft td->td_retval[0] = p->p_pid; 7676ee093fbSMike Barcroft p->p_flag &= ~P_CONTINUED; 7686ee093fbSMike Barcroft PROC_UNLOCK(p); 7696ee093fbSMike Barcroft 7706ee093fbSMike Barcroft if (uap->status) { 7716ee093fbSMike Barcroft status = SIGCONT; 7727f05b035SAlfred Perlstein error = copyout(&status, 7737f05b035SAlfred Perlstein uap->status, sizeof(status)); 7746ee093fbSMike Barcroft } else 7756ee093fbSMike Barcroft error = 0; 7766ee093fbSMike Barcroft 7776ee093fbSMike Barcroft mtx_unlock(&Giant); 7786ee093fbSMike Barcroft return (error); 7796ee093fbSMike Barcroft } 780d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 781d7aadbf9SJohn Baldwin } 782d7aadbf9SJohn Baldwin if (nfound == 0) { 783d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 784d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 785d7aadbf9SJohn Baldwin return (ECHILD); 786d7aadbf9SJohn Baldwin } 787d7aadbf9SJohn Baldwin if (uap->options & WNOHANG) { 788d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 789d7aadbf9SJohn Baldwin td->td_retval[0] = 0; 790d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 791d7aadbf9SJohn Baldwin return (0); 792d7aadbf9SJohn Baldwin } 793d7aadbf9SJohn Baldwin PROC_LOCK(q); 794d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 7957f05b035SAlfred Perlstein error = msleep(q, &q->p_mtx, PWAIT | PCATCH, "wait", 0); 796d7aadbf9SJohn Baldwin PROC_UNLOCK(q); 797d7aadbf9SJohn Baldwin if (error) { 798d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 799d7aadbf9SJohn Baldwin return (error); 800d7aadbf9SJohn Baldwin } 801d7aadbf9SJohn Baldwin goto loop; 802d7aadbf9SJohn Baldwin } 803df8bae1dSRodney W. Grimes 804df8bae1dSRodney W. Grimes /* 80598f03f90SJake Burkholder * Make process 'parent' the new parent of process 'child'. 80698f03f90SJake Burkholder * Must be called with an exclusive hold of proctree lock. 807df8bae1dSRodney W. Grimes */ 808df8bae1dSRodney W. Grimes void 809df8bae1dSRodney W. Grimes proc_reparent(child, parent) 810df8bae1dSRodney W. Grimes register struct proc *child; 811df8bae1dSRodney W. Grimes register struct proc *parent; 812df8bae1dSRodney W. Grimes { 813df8bae1dSRodney W. Grimes 8144e5e677bSJohn Baldwin sx_assert(&proctree_lock, SX_XLOCKED); 815c65437a3SJohn Baldwin PROC_LOCK_ASSERT(child, MA_OWNED); 816df8bae1dSRodney W. Grimes if (child->p_pptr == parent) 817df8bae1dSRodney W. Grimes return; 818df8bae1dSRodney W. Grimes 819b75356e1SJeffrey Hsu LIST_REMOVE(child, p_sibling); 820b75356e1SJeffrey Hsu LIST_INSERT_HEAD(&parent->p_children, child, p_sibling); 821df8bae1dSRodney W. Grimes child->p_pptr = parent; 822df8bae1dSRodney W. Grimes } 823fed06968SJulian Elischer 824e0d898b4SJulian Elischer /* 825e0d898b4SJulian Elischer * The next two functions are to handle adding/deleting items on the 826fed06968SJulian Elischer * exit callout list 827e0d898b4SJulian Elischer * 828e0d898b4SJulian Elischer * at_exit(): 829e0d898b4SJulian Elischer * Take the arguments given and put them onto the exit callout list, 830fed06968SJulian Elischer * However first make sure that it's not already there. 831fed06968SJulian Elischer * returns 0 on success. 832fed06968SJulian Elischer */ 83393efcae8SPoul-Henning Kamp 834fed06968SJulian Elischer int 835eb776aeaSBruce Evans at_exit(function) 836eb776aeaSBruce Evans exitlist_fn function; 837fed06968SJulian Elischer { 83893efcae8SPoul-Henning Kamp struct exitlist *ep; 839e0d898b4SJulian Elischer 84093efcae8SPoul-Henning Kamp #ifdef INVARIANTS 841e0d898b4SJulian Elischer /* Be noisy if the programmer has lost track of things */ 842e0d898b4SJulian Elischer if (rm_at_exit(function)) 84393efcae8SPoul-Henning Kamp printf("WARNING: exit callout entry (%p) already present\n", 84493efcae8SPoul-Henning Kamp function); 84593efcae8SPoul-Henning Kamp #endif 84693efcae8SPoul-Henning Kamp ep = malloc(sizeof(*ep), M_ATEXIT, M_NOWAIT); 847e0d898b4SJulian Elischer if (ep == NULL) 848e0d898b4SJulian Elischer return (ENOMEM); 849fed06968SJulian Elischer ep->function = function; 85093efcae8SPoul-Henning Kamp TAILQ_INSERT_TAIL(&exit_list, ep, next); 851e0d898b4SJulian Elischer return (0); 852fed06968SJulian Elischer } 85393efcae8SPoul-Henning Kamp 854fed06968SJulian Elischer /* 85593efcae8SPoul-Henning Kamp * Scan the exit callout list for the given item and remove it. 85693efcae8SPoul-Henning Kamp * Returns the number of items removed (0 or 1) 857fed06968SJulian Elischer */ 858fed06968SJulian Elischer int 859eb776aeaSBruce Evans rm_at_exit(function) 860eb776aeaSBruce Evans exitlist_fn function; 861fed06968SJulian Elischer { 86293efcae8SPoul-Henning Kamp struct exitlist *ep; 863fed06968SJulian Elischer 86493efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &exit_list, next) { 865fed06968SJulian Elischer if (ep->function == function) { 86693efcae8SPoul-Henning Kamp TAILQ_REMOVE(&exit_list, ep, next); 86793efcae8SPoul-Henning Kamp free(ep, M_ATEXIT); 86893efcae8SPoul-Henning Kamp return (1); 869fed06968SJulian Elischer } 870fed06968SJulian Elischer } 87193efcae8SPoul-Henning Kamp return (0); 872fed06968SJulian Elischer } 873