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; 138d7aadbf9SJohn Baldwin #endif 139df8bae1dSRodney W. Grimes 1400cddd8f0SMatthew Dillon GIANT_REQUIRED; 1410cddd8f0SMatthew Dillon 142276c5169SJohn Baldwin p = td->td_proc; 143e746d950SJohn Baldwin if (p == initproc) { 1445f7bd355SPoul-Henning Kamp printf("init died (signal %d, exit %d)\n", 145df8bae1dSRodney W. Grimes WTERMSIG(rv), WEXITSTATUS(rv)); 1465f7bd355SPoul-Henning Kamp panic("Going nowhere without my init!"); 1475f7bd355SPoul-Henning Kamp } 1482c1011f7SJohn Dyson 1497a6b989bSJohn Baldwin /* 1505215b187SJeff Roberson * XXXKSE: MUST abort all other threads before proceeding past here. 1517a6b989bSJohn Baldwin */ 152e602ba25SJulian Elischer PROC_LOCK(p); 153ac2e4153SJulian Elischer if (p->p_flag & P_THREADED) { 154e602ba25SJulian Elischer /* 155e602ba25SJulian Elischer * First check if some other thread got here before us.. 156e602ba25SJulian Elischer * if so, act apropriatly, (exit or suspend); 157e602ba25SJulian Elischer */ 158e602ba25SJulian Elischer thread_suspend_check(0); 159e602ba25SJulian Elischer 160e602ba25SJulian Elischer /* 161e602ba25SJulian Elischer * Kill off the other threads. This requires 162e602ba25SJulian Elischer * Some co-operation from other parts of the kernel 163e602ba25SJulian Elischer * so it may not be instant. 164e602ba25SJulian Elischer * With this state set: 165e602ba25SJulian Elischer * Any thread entering the kernel from userspace will 166e602ba25SJulian Elischer * thread_exit() in trap(). Any thread attempting to 167e602ba25SJulian Elischer * sleep will return immediatly 168e602ba25SJulian Elischer * with EINTR or EWOULDBLOCK, which will hopefully force them 169e602ba25SJulian Elischer * to back out to userland, freeing resources as they go, and 170e602ba25SJulian Elischer * anything attempting to return to userland will thread_exit() 171e602ba25SJulian Elischer * from userret(). thread_exit() will unsuspend us 172e602ba25SJulian Elischer * when the last other thread exits. 173e602ba25SJulian Elischer */ 1741279572aSDavid Xu if (thread_single(SINGLE_EXIT)) { 175e602ba25SJulian Elischer panic ("Exit: Single threading fouled up"); 176e602ba25SJulian Elischer } 177e602ba25SJulian Elischer /* 178e602ba25SJulian Elischer * All other activity in this process is now stopped. 179e602ba25SJulian Elischer * Remove excess KSEs and KSEGRPS. XXXKSE (when we have them) 180e602ba25SJulian Elischer * ... 181e602ba25SJulian Elischer * Turn off threading support. 182e602ba25SJulian Elischer */ 183ac2e4153SJulian Elischer p->p_flag &= ~P_THREADED; 184e602ba25SJulian Elischer thread_single_end(); /* Don't need this any more. */ 185e602ba25SJulian Elischer } 186e602ba25SJulian Elischer /* 187e602ba25SJulian Elischer * With this state set: 188e602ba25SJulian Elischer * Any thread entering the kernel from userspace will thread_exit() 189e602ba25SJulian Elischer * in trap(). Any thread attempting to sleep will return immediatly 190e602ba25SJulian Elischer * with EINTR or EWOULDBLOCK, which will hopefully force them 191e602ba25SJulian Elischer * to back out to userland, freeing resources as they go, and 192e602ba25SJulian Elischer * anything attempting to return to userland will thread_exit() 193e602ba25SJulian Elischer * from userret(). thread_exit() will do a wakeup on p->p_numthreads 194e602ba25SJulian Elischer * if it transitions to 1. 195e602ba25SJulian Elischer */ 196e602ba25SJulian Elischer 197e602ba25SJulian Elischer p->p_flag |= P_WEXIT; 198e602ba25SJulian Elischer PROC_UNLOCK(p); 199b40ce416SJulian Elischer 2007a6b989bSJohn Baldwin /* Are we a task leader? */ 2012c1011f7SJohn Dyson if (p == p->p_leader) { 202c6544064SJohn Baldwin mtx_lock(&ppeers_lock); 2032c1011f7SJohn Dyson q = p->p_peers; 204776e0b36SJohn Baldwin while (q != NULL) { 205776e0b36SJohn Baldwin PROC_LOCK(q); 206776e0b36SJohn Baldwin psignal(q, SIGKILL); 207776e0b36SJohn Baldwin PROC_UNLOCK(q); 2082c1011f7SJohn Dyson q = q->p_peers; 2092c1011f7SJohn Dyson } 210c6544064SJohn Baldwin while (p->p_peers != NULL) 211c6544064SJohn Baldwin msleep(p, &ppeers_lock, PWAIT, "exit1", 0); 212c6544064SJohn Baldwin mtx_unlock(&ppeers_lock); 2132c1011f7SJohn Dyson } 2142c1011f7SJohn Dyson 215df8bae1dSRodney W. Grimes #ifdef PGINPROF 216df8bae1dSRodney W. Grimes vmsizmon(); 217df8bae1dSRodney W. Grimes #endif 2182a024a2bSSean Eric Fagan STOPEVENT(p, S_EXIT, rv); 21989361835SSean Eric Fagan wakeup(&p->p_stype); /* Wakeup anyone in procfs' PIOCWAIT */ 2202a024a2bSSean Eric Fagan 221fed06968SJulian Elischer /* 222e9189611SPeter Wemm * Check if any loadable modules need anything done at process exit. 223fed06968SJulian Elischer * e.g. SYSV IPC stuff 224fed06968SJulian Elischer * XXX what if one of these generates an error? 225fed06968SJulian Elischer */ 22693efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &exit_list, next) 227fed06968SJulian Elischer (*ep->function)(p); 228fed06968SJulian Elischer 229a914fb6bSJohn Baldwin 230df8bae1dSRodney W. Grimes MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 231a163d034SWarner Losh M_ZOMBIE, M_WAITOK); 232df8bae1dSRodney W. Grimes /* 233df8bae1dSRodney W. Grimes * If parent is waiting for us to exit or exec, 234df8bae1dSRodney W. Grimes * P_PPWAIT is set; we will wakeup the parent below. 235df8bae1dSRodney W. Grimes */ 236a914fb6bSJohn Baldwin PROC_LOCK(p); 237a282253aSJulian Elischer stopprofclock(p); 238df8bae1dSRodney W. Grimes p->p_flag &= ~(P_TRACED | P_PPWAIT); 2391d9c5696SJuli Mallett SIGEMPTYSET(p->p_siglist); 2404cf41af3SPoul-Henning Kamp if (timevalisset(&p->p_realtimer.it_value)) 2414f559836SJake Burkholder callout_stop(&p->p_itcallout); 24296d7f8efSTim J. Robbins PROC_UNLOCK(p); 243df8bae1dSRodney W. Grimes 244df8bae1dSRodney W. Grimes /* 245831d27a9SDon Lewis * Reset any sigio structures pointing to us as a result of 246831d27a9SDon Lewis * F_SETOWN with our pid. 247831d27a9SDon Lewis */ 248831d27a9SDon Lewis funsetownlst(&p->p_sigiolst); 249831d27a9SDon Lewis 250831d27a9SDon Lewis /* 251df8bae1dSRodney W. Grimes * Close open files and release open-file table. 252df8bae1dSRodney W. Grimes * This may block! 253df8bae1dSRodney W. Grimes */ 254edf6699aSAlfred Perlstein fdfree(td); 255df8bae1dSRodney W. Grimes 256a914fb6bSJohn Baldwin /* 257a914fb6bSJohn Baldwin * Remove ourself from our leader's peer list and wake our leader. 258a914fb6bSJohn Baldwin */ 259c6544064SJohn Baldwin mtx_lock(&ppeers_lock); 26079fc0bf4SMike Smith if (p->p_leader->p_peers) { 26179fc0bf4SMike Smith q = p->p_leader; 26279fc0bf4SMike Smith while (q->p_peers != p) 26379fc0bf4SMike Smith q = q->p_peers; 26479fc0bf4SMike Smith q->p_peers = p->p_peers; 2657f05b035SAlfred Perlstein wakeup(p->p_leader); 26679fc0bf4SMike Smith } 267c6544064SJohn Baldwin mtx_unlock(&ppeers_lock); 26879fc0bf4SMike Smith 269df8bae1dSRodney W. Grimes /* The next two chunks should probably be moved to vmspace_exit. */ 270df8bae1dSRodney W. Grimes vm = p->p_vmspace; 271df8bae1dSRodney W. Grimes /* 272df8bae1dSRodney W. Grimes * Release user portion of address space. 273df8bae1dSRodney W. Grimes * This releases references to vnodes, 274df8bae1dSRodney W. Grimes * which could cause I/O if the file has been unlinked. 275df8bae1dSRodney W. Grimes * Need to do this early enough that we can still sleep. 276df8bae1dSRodney W. Grimes * Can't free the entire vmspace as the kernel stack 277df8bae1dSRodney W. Grimes * may be mapped within that space also. 278389d2b6eSMatthew Dillon * 279389d2b6eSMatthew Dillon * Processes sharing the same vmspace may exit in one order, and 280389d2b6eSMatthew Dillon * get cleaned up by vmspace_exit() in a different order. The 281389d2b6eSMatthew Dillon * last exiting process to reach this point releases as much of 282389d2b6eSMatthew Dillon * the environment as it can, and the last process cleaned up 283389d2b6eSMatthew Dillon * by vmspace_exit() (which decrements exitingcnt) cleans up the 284389d2b6eSMatthew Dillon * remainder. 285df8bae1dSRodney W. Grimes */ 286389d2b6eSMatthew Dillon ++vm->vm_exitingcnt; 287582ec34cSAlfred Perlstein if (--vm->vm_refcnt == 0) { 2883db161e0SMatthew Dillon shmexit(vm); 2892d21129dSAlan Cox vm_page_lock_queues(); 29005ba50f5SJake Burkholder pmap_remove_pages(vmspace_pmap(vm), vm_map_min(&vm->vm_map), 29105ba50f5SJake Burkholder vm_map_max(&vm->vm_map)); 2922d21129dSAlan Cox vm_page_unlock_queues(); 29305ba50f5SJake Burkholder (void) vm_map_remove(&vm->vm_map, vm_map_min(&vm->vm_map), 29405ba50f5SJake Burkholder vm_map_max(&vm->vm_map)); 2959d3fbbb5SJohn Dyson } 296df8bae1dSRodney W. Grimes 297ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 298df8bae1dSRodney W. Grimes if (SESS_LEADER(p)) { 299f591779bSSeigo Tanimura register struct session *sp; 300df8bae1dSRodney W. Grimes 301f591779bSSeigo Tanimura sp = p->p_session; 302df8bae1dSRodney W. Grimes if (sp->s_ttyvp) { 303df8bae1dSRodney W. Grimes /* 304df8bae1dSRodney W. Grimes * Controlling process. 305df8bae1dSRodney W. Grimes * Signal foreground pgrp, 306df8bae1dSRodney W. Grimes * drain controlling terminal 307df8bae1dSRodney W. Grimes * and revoke access to controlling terminal. 308df8bae1dSRodney W. Grimes */ 309dd45d8adSJulian Elischer if (sp->s_ttyp && (sp->s_ttyp->t_session == sp)) { 310f591779bSSeigo Tanimura tp = sp->s_ttyp; 311f591779bSSeigo Tanimura if (sp->s_ttyp->t_pgrp) { 312f591779bSSeigo Tanimura PGRP_LOCK(sp->s_ttyp->t_pgrp); 313df8bae1dSRodney W. Grimes pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 314f591779bSSeigo Tanimura PGRP_UNLOCK(sp->s_ttyp->t_pgrp); 315f591779bSSeigo Tanimura } 316f591779bSSeigo Tanimura /* XXX tp should be locked. */ 317ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 318f591779bSSeigo Tanimura (void) ttywait(tp); 319ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 320df8bae1dSRodney W. Grimes /* 321df8bae1dSRodney W. Grimes * The tty could have been revoked 322df8bae1dSRodney W. Grimes * if we blocked. 323df8bae1dSRodney W. Grimes */ 324f591779bSSeigo Tanimura if (sp->s_ttyvp) { 325f591779bSSeigo Tanimura ttyvp = sp->s_ttyvp; 326f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 327df8bae1dSRodney W. Grimes sp->s_ttyvp = NULL; 328f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 329ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 330f591779bSSeigo Tanimura VOP_REVOKE(ttyvp, REVOKEALL); 331f591779bSSeigo Tanimura vrele(ttyvp); 332ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 333f591779bSSeigo Tanimura } 334f591779bSSeigo Tanimura } 335f591779bSSeigo Tanimura if (sp->s_ttyvp) { 336f591779bSSeigo Tanimura ttyvp = sp->s_ttyvp; 337f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 338f591779bSSeigo Tanimura sp->s_ttyvp = NULL; 339f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 340f591779bSSeigo Tanimura vrele(ttyvp); 341f591779bSSeigo Tanimura } 342df8bae1dSRodney W. Grimes /* 343df8bae1dSRodney W. Grimes * s_ttyp is not zero'd; we use this to indicate 344df8bae1dSRodney W. Grimes * that the session once had a controlling terminal. 345df8bae1dSRodney W. Grimes * (for logging and informational purposes) 346df8bae1dSRodney W. Grimes */ 347df8bae1dSRodney W. Grimes } 348f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 349df8bae1dSRodney W. Grimes sp->s_leader = NULL; 350f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 351f591779bSSeigo Tanimura } 352df8bae1dSRodney W. Grimes fixjobc(p, p->p_pgrp, 0); 353ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 354b40ce416SJulian Elischer (void)acct_process(td); 355df8bae1dSRodney W. Grimes #ifdef KTRACE 356df8bae1dSRodney W. Grimes /* 357df8bae1dSRodney W. Grimes * release trace file 358df8bae1dSRodney W. Grimes */ 359d7aadbf9SJohn Baldwin PROC_LOCK(p); 3606c84de02SJohn Baldwin mtx_lock(&ktrace_mtx); 361df8bae1dSRodney W. Grimes p->p_traceflag = 0; /* don't trace the vrele() */ 362d7aadbf9SJohn Baldwin tracevp = p->p_tracep; 36379deba82SMatthew Dillon p->p_tracep = NULL; 3646c84de02SJohn Baldwin mtx_unlock(&ktrace_mtx); 365d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 366d7aadbf9SJohn Baldwin if (tracevp != NULL) 367d7aadbf9SJohn Baldwin vrele(tracevp); 368df8bae1dSRodney W. Grimes #endif 369df8bae1dSRodney W. Grimes /* 370ee42d0a9SDavid Malone * Release reference to text vnode 371ee42d0a9SDavid Malone */ 372ee42d0a9SDavid Malone if ((vtmp = p->p_textvp) != NULL) { 373ee42d0a9SDavid Malone p->p_textvp = NULL; 374ee42d0a9SDavid Malone vrele(vtmp); 375ee42d0a9SDavid Malone } 376ee42d0a9SDavid Malone 377ee42d0a9SDavid Malone /* 378d7aadbf9SJohn Baldwin * Release our limits structure. 379d7aadbf9SJohn Baldwin */ 380d7aadbf9SJohn Baldwin mtx_assert(&Giant, MA_OWNED); 381d7aadbf9SJohn Baldwin if (--p->p_limit->p_refcnt == 0) { 382d7aadbf9SJohn Baldwin FREE(p->p_limit, M_SUBPROC); 383d7aadbf9SJohn Baldwin p->p_limit = NULL; 384d7aadbf9SJohn Baldwin } 385d7aadbf9SJohn Baldwin 386d7aadbf9SJohn Baldwin /* 387d7aadbf9SJohn Baldwin * Release this thread's reference to the ucred. The actual proc 388d7aadbf9SJohn Baldwin * reference will stay around until the proc is harvested by 389d7aadbf9SJohn Baldwin * wait(). At this point the ucred is immutable (no other threads 390d7aadbf9SJohn Baldwin * from this proc are around that can change it) so we leave the 391d7aadbf9SJohn Baldwin * per-thread ucred pointer intact in case it is needed although 392d7aadbf9SJohn Baldwin * in theory nothing should be using it at this point. 393d7aadbf9SJohn Baldwin */ 394d7aadbf9SJohn Baldwin crfree(td->td_ucred); 395d7aadbf9SJohn Baldwin 396d7aadbf9SJohn Baldwin /* 397df8bae1dSRodney W. Grimes * Remove proc from allproc queue and pidhash chain. 398df8bae1dSRodney W. Grimes * Place onto zombproc. Unlink from parent's child list. 399df8bae1dSRodney W. Grimes */ 4001005a129SJohn Baldwin sx_xlock(&allproc_lock); 401b75356e1SJeffrey Hsu LIST_REMOVE(p, p_list); 402b75356e1SJeffrey Hsu LIST_INSERT_HEAD(&zombproc, p, p_list); 403b75356e1SJeffrey Hsu LIST_REMOVE(p, p_hash); 4041005a129SJohn Baldwin sx_xunlock(&allproc_lock); 405df8bae1dSRodney W. Grimes 4061005a129SJohn Baldwin sx_xlock(&proctree_lock); 4072e3c8fcbSPoul-Henning Kamp q = LIST_FIRST(&p->p_children); 408a914fb6bSJohn Baldwin if (q != NULL) /* only need this if any child is S_ZOMB */ 4097f05b035SAlfred Perlstein wakeup(initproc); 410a914fb6bSJohn Baldwin for (; q != NULL; q = nq) { 4112e3c8fcbSPoul-Henning Kamp nq = LIST_NEXT(q, p_sibling); 412a914fb6bSJohn Baldwin PROC_LOCK(q); 413c65437a3SJohn Baldwin proc_reparent(q, initproc); 4144ac9ae70SJulian Elischer q->p_sigparent = SIGCHLD; 415df8bae1dSRodney W. Grimes /* 416df8bae1dSRodney W. Grimes * Traced processes are killed 417df8bae1dSRodney W. Grimes * since their existence means someone is screwing up. 418df8bae1dSRodney W. Grimes */ 419df8bae1dSRodney W. Grimes if (q->p_flag & P_TRACED) { 420df8bae1dSRodney W. Grimes q->p_flag &= ~P_TRACED; 421df8bae1dSRodney W. Grimes psignal(q, SIGKILL); 422c65437a3SJohn Baldwin } 423a914fb6bSJohn Baldwin PROC_UNLOCK(q); 424df8bae1dSRodney W. Grimes } 425df8bae1dSRodney W. Grimes 426df8bae1dSRodney W. Grimes /* 427df8bae1dSRodney W. Grimes * Save exit status and final rusage info, adding in child rusage 428df8bae1dSRodney W. Grimes * info and self times. 429df8bae1dSRodney W. Grimes */ 430d7aadbf9SJohn Baldwin PROC_LOCK(p); 431df8bae1dSRodney W. Grimes p->p_xstat = rv; 432df8bae1dSRodney W. Grimes *p->p_ru = p->p_stats->p_ru; 4339ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 434df8bae1dSRodney W. Grimes calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL); 4359ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 436df8bae1dSRodney W. Grimes ruadd(p->p_ru, &p->p_stats->p_cru); 437df8bae1dSRodney W. Grimes 438df8bae1dSRodney W. Grimes /* 4397a6b989bSJohn Baldwin * Notify interested parties of our demise. 440cb679c38SJonathan Lemon */ 441a274d19bSBrian Feldman KNOTE(&p->p_klist, NOTE_EXIT); 442cb679c38SJonathan Lemon 443cb679c38SJonathan Lemon /* 444645682fdSLuoqi Chen * Notify parent that we're gone. If parent has the PS_NOCLDWAIT 445ba1551caSIan Dowse * flag set, or if the handler is set to SIG_IGN, notify process 446ba1551caSIan Dowse * 1 instead (and hope it will handle this situation). 447df8bae1dSRodney W. Grimes */ 448d7aadbf9SJohn Baldwin PROC_LOCK(p->p_pptr); 449ba1551caSIan Dowse if (p->p_pptr->p_procsig->ps_flag & (PS_NOCLDWAIT | PS_CLDSIGIGN)) { 450276c5169SJohn Baldwin struct proc *pp; 451276c5169SJohn Baldwin 452276c5169SJohn Baldwin pp = p->p_pptr; 453f591779bSSeigo Tanimura PROC_UNLOCK(pp); 454245f17d4SJoerg Wunsch proc_reparent(p, initproc); 455f591779bSSeigo Tanimura PROC_LOCK(p->p_pptr); 456245f17d4SJoerg Wunsch /* 457245f17d4SJoerg Wunsch * If this was the last child of our parent, notify 458245f17d4SJoerg Wunsch * parent, so in case he was wait(2)ing, he will 459245f17d4SJoerg Wunsch * continue. 460245f17d4SJoerg Wunsch */ 461245f17d4SJoerg Wunsch if (LIST_EMPTY(&pp->p_children)) 4627f05b035SAlfred Perlstein wakeup(pp); 463245f17d4SJoerg Wunsch } 464245f17d4SJoerg Wunsch 465c65437a3SJohn Baldwin if (p->p_sigparent && p->p_pptr != initproc) 4666626c604SJulian Elischer psignal(p->p_pptr, p->p_sigparent); 467c65437a3SJohn Baldwin else 4686626c604SJulian Elischer psignal(p->p_pptr, SIGCHLD); 469c65437a3SJohn Baldwin PROC_UNLOCK(p->p_pptr); 470776e0b36SJohn Baldwin 471776e0b36SJohn Baldwin /* 472776e0b36SJohn Baldwin * If this is a kthread, then wakeup anyone waiting for it to exit. 473776e0b36SJohn Baldwin */ 474776e0b36SJohn Baldwin if (p->p_flag & P_KTHREAD) 4757f05b035SAlfred Perlstein wakeup(p); 476c65437a3SJohn Baldwin PROC_UNLOCK(p); 4778e2e767bSJohn Baldwin 4788e2e767bSJohn Baldwin /* 479df8bae1dSRodney W. Grimes * Finally, call machine-dependent code to release the remaining 480696058c3SJulian Elischer * resources including address space. 481582ec34cSAlfred Perlstein * The address space is released by "vmspace_exitfree(p)" in 482582ec34cSAlfred Perlstein * vm_waitproc(). 483df8bae1dSRodney W. Grimes */ 484b40ce416SJulian Elischer cpu_exit(td); 485eb30c1c0SPeter Wemm 486eb30c1c0SPeter Wemm PROC_LOCK(p); 487d7aadbf9SJohn Baldwin PROC_LOCK(p->p_pptr); 488d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 489eb30c1c0SPeter Wemm mtx_lock_spin(&sched_lock); 490696058c3SJulian Elischer 491eb30c1c0SPeter Wemm while (mtx_owned(&Giant)) 492c86b6ff5SJohn Baldwin mtx_unlock(&Giant); 493eb30c1c0SPeter Wemm 494eb30c1c0SPeter Wemm /* 495eb30c1c0SPeter Wemm * We have to wait until after releasing all locks before 496e602ba25SJulian Elischer * changing p_state. If we block on a mutex then we will be 497eb30c1c0SPeter Wemm * back at SRUN when we resume and our parent will never 498eb30c1c0SPeter Wemm * harvest us. 499eb30c1c0SPeter Wemm */ 500e602ba25SJulian Elischer p->p_state = PRS_ZOMBIE; 501eb30c1c0SPeter Wemm 502eb30c1c0SPeter Wemm wakeup(p->p_pptr); 503d7aadbf9SJohn Baldwin PROC_UNLOCK(p->p_pptr); 504eb30c1c0SPeter Wemm cnt.v_swtch++; 505d7aadbf9SJohn Baldwin binuptime(PCPU_PTR(switchtime)); 506d7aadbf9SJohn Baldwin PCPU_SET(switchticks, ticks); 507d7aadbf9SJohn Baldwin 508e602ba25SJulian Elischer cpu_sched_exit(td); /* XXXKSE check if this should be in thread_exit */ 509e602ba25SJulian Elischer /* 510696058c3SJulian Elischer * Make sure the scheduler takes this thread out of its tables etc. 511e602ba25SJulian Elischer * This will also release this thread's reference to the ucred. 512696058c3SJulian Elischer * Other thread parts to release include pcb bits and such. 513e602ba25SJulian Elischer */ 514e602ba25SJulian Elischer thread_exit(); 515df8bae1dSRodney W. Grimes } 516df8bae1dSRodney W. Grimes 517b2f9e8b1SBruce Evans #ifdef COMPAT_43 518234216efSMatthew Dillon /* 5197a6b989bSJohn Baldwin * MPSAFE. The dirty work is handled by wait1(). 520234216efSMatthew Dillon */ 52126f9a767SRodney W. Grimes int 522b40ce416SJulian Elischer owait(td, uap) 523b40ce416SJulian Elischer struct thread *td; 5245fdb8324SBruce Evans register struct owait_args /* { 5255fdb8324SBruce Evans int dummy; 5265fdb8324SBruce Evans } */ *uap; 527df8bae1dSRodney W. Grimes { 52893c9414eSSteven Wallace struct wait_args w; 529df8bae1dSRodney W. Grimes 53093c9414eSSteven Wallace w.options = 0; 53193c9414eSSteven Wallace w.rusage = NULL; 53293c9414eSSteven Wallace w.pid = WAIT_ANY; 53393c9414eSSteven Wallace w.status = NULL; 534b40ce416SJulian Elischer return (wait1(td, &w, 1)); 535df8bae1dSRodney W. Grimes } 536b2f9e8b1SBruce Evans #endif /* COMPAT_43 */ 537df8bae1dSRodney W. Grimes 538234216efSMatthew Dillon /* 5397a6b989bSJohn Baldwin * MPSAFE. The dirty work is handled by wait1(). 540234216efSMatthew Dillon */ 54126f9a767SRodney W. Grimes int 542b40ce416SJulian Elischer wait4(td, uap) 543b40ce416SJulian Elischer struct thread *td; 544df8bae1dSRodney W. Grimes struct wait_args *uap; 545df8bae1dSRodney W. Grimes { 546b40ce416SJulian Elischer 547b40ce416SJulian Elischer return (wait1(td, uap, 0)); 548df8bae1dSRodney W. Grimes } 549df8bae1dSRodney W. Grimes 550234216efSMatthew Dillon /* 551234216efSMatthew Dillon * MPSAFE 552234216efSMatthew Dillon */ 55393c9414eSSteven Wallace static int 554b40ce416SJulian Elischer wait1(td, uap, compat) 555b40ce416SJulian Elischer register struct thread *td; 5565fdb8324SBruce Evans register struct wait_args /* { 5575fdb8324SBruce Evans int pid; 5585fdb8324SBruce Evans int *status; 5595fdb8324SBruce Evans int options; 5605fdb8324SBruce Evans struct rusage *rusage; 5615fdb8324SBruce Evans } */ *uap; 56293c9414eSSteven Wallace int compat; 563df8bae1dSRodney W. Grimes { 564276c5169SJohn Baldwin struct rusage ru; 56548bfcdddSJulian Elischer int nfound; 56648bfcdddSJulian Elischer struct proc *p, *q, *t; 567f23c6d68SSteven Wallace int status, error; 568df8bae1dSRodney W. Grimes 569b40ce416SJulian Elischer q = td->td_proc; 570f591779bSSeigo Tanimura if (uap->pid == 0) { 571f591779bSSeigo Tanimura PROC_LOCK(q); 572df8bae1dSRodney W. Grimes uap->pid = -q->p_pgid; 573f591779bSSeigo Tanimura PROC_UNLOCK(q); 574f591779bSSeigo Tanimura } 5756ee093fbSMike Barcroft if (uap->options &~ (WUNTRACED|WNOHANG|WCONTINUED|WLINUXCLONE)) 5766dc958b9SJohn Baldwin return (EINVAL); 5776dc958b9SJohn Baldwin mtx_lock(&Giant); 578df8bae1dSRodney W. Grimes loop: 579df8bae1dSRodney W. Grimes nfound = 0; 580d7aadbf9SJohn Baldwin sx_xlock(&proctree_lock); 5812e3c8fcbSPoul-Henning Kamp LIST_FOREACH(p, &q->p_children, p_sibling) { 582f591779bSSeigo Tanimura PROC_LOCK(p); 583df8bae1dSRodney W. Grimes if (uap->pid != WAIT_ANY && 584f591779bSSeigo Tanimura p->p_pid != uap->pid && p->p_pgid != -uap->pid) { 585f591779bSSeigo Tanimura PROC_UNLOCK(p); 586df8bae1dSRodney W. Grimes continue; 587f591779bSSeigo Tanimura } 5884ac9ae70SJulian Elischer 5891156bc4dSJake Burkholder /* 5901156bc4dSJake Burkholder * This special case handles a kthread spawned by linux_clone 5911156bc4dSJake Burkholder * (see linux_misc.c). The linux_wait4 and linux_waitpid 5921156bc4dSJake Burkholder * functions need to be able to distinguish between waiting 5931156bc4dSJake Burkholder * on a process and waiting on a thread. It is a thread if 5941156bc4dSJake Burkholder * p_sigparent is not SIGCHLD, and the WLINUXCLONE option 5951156bc4dSJake Burkholder * signifies we want to wait for threads and not processes. 5964ac9ae70SJulian Elischer */ 5971156bc4dSJake Burkholder if ((p->p_sigparent != SIGCHLD) ^ 598a914fb6bSJohn Baldwin ((uap->options & WLINUXCLONE) != 0)) { 599a914fb6bSJohn Baldwin PROC_UNLOCK(p); 6004ac9ae70SJulian Elischer continue; 601a914fb6bSJohn Baldwin } 6024ac9ae70SJulian Elischer 603df8bae1dSRodney W. Grimes nfound++; 604e602ba25SJulian Elischer if (p->p_state == PRS_ZOMBIE) { 605b40ce416SJulian Elischer /* 606b43179fbSJeff Roberson * Allow the scheduler to adjust the priority of the 607b43179fbSJeff Roberson * parent when a kseg is exiting. 608b40ce416SJulian Elischer */ 609b40ce416SJulian Elischer if (curthread->td_proc->p_pid != 1) { 610d7aadbf9SJohn Baldwin mtx_lock_spin(&sched_lock); 611b43179fbSJeff Roberson sched_exit(curthread->td_ksegrp, 612b43179fbSJeff Roberson FIRST_KSEGRP_IN_PROC(p)); 613c65437a3SJohn Baldwin mtx_unlock_spin(&sched_lock); 614d7aadbf9SJohn Baldwin } 615c65437a3SJohn Baldwin 616b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 617b2f9e8b1SBruce Evans #ifdef COMPAT_43 61893c9414eSSteven Wallace if (compat) 619b40ce416SJulian Elischer td->td_retval[1] = p->p_xstat; 620df8bae1dSRodney W. Grimes else 621df8bae1dSRodney W. Grimes #endif 622df8bae1dSRodney W. Grimes if (uap->status) { 623df8bae1dSRodney W. Grimes status = p->p_xstat; /* convert to int */ 624d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 6257f05b035SAlfred Perlstein if ((error = copyout(&status, 6267f05b035SAlfred Perlstein uap->status, sizeof(status)))) { 627d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 628d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 629d7aadbf9SJohn Baldwin return (error); 630234216efSMatthew Dillon } 631d7aadbf9SJohn Baldwin PROC_LOCK(p); 632df8bae1dSRodney W. Grimes } 633d7aadbf9SJohn Baldwin if (uap->rusage) { 634d7aadbf9SJohn Baldwin bcopy(p->p_ru, &ru, sizeof(ru)); 635d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 6367f05b035SAlfred Perlstein if ((error = copyout(&ru, 6377f05b035SAlfred Perlstein uap->rusage, sizeof (struct rusage)))) { 638d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 639d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 640d7aadbf9SJohn Baldwin return (error); 641234216efSMatthew Dillon } 642d7aadbf9SJohn Baldwin } else 643d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 644df8bae1dSRodney W. Grimes /* 645df8bae1dSRodney W. Grimes * If we got the child via a ptrace 'attach', 646df8bae1dSRodney W. Grimes * we need to give it back to the old parent. 647df8bae1dSRodney W. Grimes */ 648d7aadbf9SJohn Baldwin if (p->p_oppid && (t = pfind(p->p_oppid)) != NULL) { 649c65437a3SJohn Baldwin PROC_LOCK(p); 650df8bae1dSRodney W. Grimes p->p_oppid = 0; 651df8bae1dSRodney W. Grimes proc_reparent(p, t); 652c65437a3SJohn Baldwin PROC_UNLOCK(p); 653df8bae1dSRodney W. Grimes psignal(t, SIGCHLD); 6547f05b035SAlfred Perlstein wakeup(t); 655c65437a3SJohn Baldwin PROC_UNLOCK(t); 6561005a129SJohn Baldwin sx_xunlock(&proctree_lock); 657d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 658d7aadbf9SJohn Baldwin return (0); 659df8bae1dSRodney W. Grimes } 660ebdc3f1dSSeigo Tanimura 6613890793eSTim J. Robbins /* 6623890793eSTim J. Robbins * Remove other references to this process to ensure 6633890793eSTim J. Robbins * we have an exclusive reference. 6643890793eSTim J. Robbins */ 6656ec62361STim J. Robbins sx_xlock(&allproc_lock); 6666ec62361STim J. Robbins LIST_REMOVE(p, p_list); /* off zombproc */ 6676ec62361STim J. Robbins sx_xunlock(&allproc_lock); 6686ec62361STim J. Robbins LIST_REMOVE(p, p_sibling); 6693890793eSTim J. Robbins leavepgrp(p); 670ebdc3f1dSSeigo Tanimura sx_xunlock(&proctree_lock); 671ebdc3f1dSSeigo Tanimura 672ebdc3f1dSSeigo Tanimura /* 673d7aadbf9SJohn Baldwin * As a side effect of this lock, we know that 674d7aadbf9SJohn Baldwin * all other writes to this proc are visible now, so 675d7aadbf9SJohn Baldwin * no more locking is needed for p. 676d7aadbf9SJohn Baldwin */ 677d7aadbf9SJohn Baldwin PROC_LOCK(p); 678d7aadbf9SJohn Baldwin p->p_xstat = 0; /* XXX: why? */ 679d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 680d7aadbf9SJohn Baldwin PROC_LOCK(q); 681d7aadbf9SJohn Baldwin ruadd(&q->p_stats->p_cru, p->p_ru); 682d7aadbf9SJohn Baldwin PROC_UNLOCK(q); 683d7aadbf9SJohn Baldwin FREE(p->p_ru, M_ZOMBIE); 684d7aadbf9SJohn Baldwin p->p_ru = NULL; 685d7aadbf9SJohn Baldwin 686d7aadbf9SJohn Baldwin /* 687d7aadbf9SJohn Baldwin * Decrement the count of procs running with this uid. 688d7aadbf9SJohn Baldwin */ 689d7aadbf9SJohn Baldwin (void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0); 690d7aadbf9SJohn Baldwin 691d7aadbf9SJohn Baldwin /* 692df8bae1dSRodney W. Grimes * Free up credentials. 693df8bae1dSRodney W. Grimes */ 694da654d90SPoul-Henning Kamp crfree(p->p_ucred); 695d7aadbf9SJohn Baldwin p->p_ucred = NULL; /* XXX: why? */ 696df8bae1dSRodney W. Grimes 697df8bae1dSRodney W. Grimes /* 698b9df5231SPoul-Henning Kamp * Remove unused arguments 699b9df5231SPoul-Henning Kamp */ 700d7aadbf9SJohn Baldwin pargs_drop(p->p_args); 701d7aadbf9SJohn Baldwin p->p_args = NULL; 702b9df5231SPoul-Henning Kamp 7036626c604SJulian Elischer if (--p->p_procsig->ps_refcnt == 0) { 704b40ce416SJulian Elischer if (p->p_sigacts != &p->p_uarea->u_sigacts) 705dc9c271aSJulian Elischer FREE(p->p_sigacts, M_SUBPROC); 706dc9c271aSJulian Elischer FREE(p->p_procsig, M_SUBPROC); 7076626c604SJulian Elischer p->p_procsig = NULL; 7086626c604SJulian Elischer } 70988c5ea45SJulian Elischer 710df8bae1dSRodney W. Grimes /* 711696058c3SJulian Elischer * do any thread-system specific cleanups 712e602ba25SJulian Elischer */ 713696058c3SJulian Elischer thread_wait(p); 714e602ba25SJulian Elischer 715e602ba25SJulian Elischer /* 716eb30c1c0SPeter Wemm * Give vm and machine-dependent layer a chance 717df8bae1dSRodney W. Grimes * to free anything that cpu_exit couldn't 718df8bae1dSRodney W. Grimes * release while still running in process context. 719df8bae1dSRodney W. Grimes */ 720eb30c1c0SPeter Wemm vm_waitproc(p); 7214971f62aSJohn Baldwin mtx_destroy(&p->p_mtx); 7222555374cSRobert Watson #ifdef MAC 7232555374cSRobert Watson mac_destroy_proc(p); 7242555374cSRobert Watson #endif 7251faf202eSJulian Elischer KASSERT(FIRST_THREAD_IN_PROC(p), 7261faf202eSJulian Elischer ("wait1: no residual thread!")); 727c897b813SJeff Roberson uma_zfree(proc_zone, p); 728d7aadbf9SJohn Baldwin sx_xlock(&allproc_lock); 729df8bae1dSRodney W. Grimes nprocs--; 730d7aadbf9SJohn Baldwin sx_xunlock(&allproc_lock); 731d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 732d7aadbf9SJohn Baldwin return (0); 733df8bae1dSRodney W. Grimes } 734e574e444SDavid Xu if (P_SHOULDSTOP(p) && (p->p_suspcount == p->p_numthreads) && 735e574e444SDavid Xu ((p->p_flag & P_WAITED) == 0) && 736df8bae1dSRodney W. Grimes (p->p_flag & P_TRACED || uap->options & WUNTRACED)) { 737df8bae1dSRodney W. Grimes p->p_flag |= P_WAITED; 738d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 739b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 740b2f9e8b1SBruce Evans #ifdef COMPAT_43 74193c9414eSSteven Wallace if (compat) { 742b40ce416SJulian Elischer td->td_retval[1] = W_STOPCODE(p->p_xstat); 743d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 744df8bae1dSRodney W. Grimes error = 0; 745df8bae1dSRodney W. Grimes } else 746df8bae1dSRodney W. Grimes #endif 747df8bae1dSRodney W. Grimes if (uap->status) { 748df8bae1dSRodney W. Grimes status = W_STOPCODE(p->p_xstat); 749d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 7507f05b035SAlfred Perlstein error = copyout(&status, 7517f05b035SAlfred Perlstein uap->status, sizeof(status)); 752d7aadbf9SJohn Baldwin } else { 753a914fb6bSJohn Baldwin PROC_UNLOCK(p); 754234216efSMatthew Dillon error = 0; 755df8bae1dSRodney W. Grimes } 756234216efSMatthew Dillon mtx_unlock(&Giant); 757234216efSMatthew Dillon return (error); 758df8bae1dSRodney W. Grimes } 7596ee093fbSMike Barcroft if (uap->options & WCONTINUED && (p->p_flag & P_CONTINUED)) { 7606ee093fbSMike Barcroft sx_xunlock(&proctree_lock); 7616ee093fbSMike Barcroft td->td_retval[0] = p->p_pid; 7626ee093fbSMike Barcroft p->p_flag &= ~P_CONTINUED; 7636ee093fbSMike Barcroft PROC_UNLOCK(p); 7646ee093fbSMike Barcroft 7656ee093fbSMike Barcroft if (uap->status) { 7666ee093fbSMike Barcroft status = SIGCONT; 7677f05b035SAlfred Perlstein error = copyout(&status, 7687f05b035SAlfred Perlstein uap->status, sizeof(status)); 7696ee093fbSMike Barcroft } else 7706ee093fbSMike Barcroft error = 0; 7716ee093fbSMike Barcroft 7726ee093fbSMike Barcroft mtx_unlock(&Giant); 7736ee093fbSMike Barcroft return (error); 7746ee093fbSMike Barcroft } 775d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 776d7aadbf9SJohn Baldwin } 777d7aadbf9SJohn Baldwin if (nfound == 0) { 778d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 779d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 780d7aadbf9SJohn Baldwin return (ECHILD); 781d7aadbf9SJohn Baldwin } 782d7aadbf9SJohn Baldwin if (uap->options & WNOHANG) { 783d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 784d7aadbf9SJohn Baldwin td->td_retval[0] = 0; 785d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 786d7aadbf9SJohn Baldwin return (0); 787d7aadbf9SJohn Baldwin } 788d7aadbf9SJohn Baldwin PROC_LOCK(q); 789d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 7907f05b035SAlfred Perlstein error = msleep(q, &q->p_mtx, PWAIT | PCATCH, "wait", 0); 791d7aadbf9SJohn Baldwin PROC_UNLOCK(q); 792d7aadbf9SJohn Baldwin if (error) { 793d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 794d7aadbf9SJohn Baldwin return (error); 795d7aadbf9SJohn Baldwin } 796d7aadbf9SJohn Baldwin goto loop; 797d7aadbf9SJohn Baldwin } 798df8bae1dSRodney W. Grimes 799df8bae1dSRodney W. Grimes /* 80098f03f90SJake Burkholder * Make process 'parent' the new parent of process 'child'. 80198f03f90SJake Burkholder * Must be called with an exclusive hold of proctree lock. 802df8bae1dSRodney W. Grimes */ 803df8bae1dSRodney W. Grimes void 804df8bae1dSRodney W. Grimes proc_reparent(child, parent) 805df8bae1dSRodney W. Grimes register struct proc *child; 806df8bae1dSRodney W. Grimes register struct proc *parent; 807df8bae1dSRodney W. Grimes { 808df8bae1dSRodney W. Grimes 8094e5e677bSJohn Baldwin sx_assert(&proctree_lock, SX_XLOCKED); 810c65437a3SJohn Baldwin PROC_LOCK_ASSERT(child, MA_OWNED); 811df8bae1dSRodney W. Grimes if (child->p_pptr == parent) 812df8bae1dSRodney W. Grimes return; 813df8bae1dSRodney W. Grimes 814b75356e1SJeffrey Hsu LIST_REMOVE(child, p_sibling); 815b75356e1SJeffrey Hsu LIST_INSERT_HEAD(&parent->p_children, child, p_sibling); 816df8bae1dSRodney W. Grimes child->p_pptr = parent; 817df8bae1dSRodney W. Grimes } 818fed06968SJulian Elischer 819e0d898b4SJulian Elischer /* 820e0d898b4SJulian Elischer * The next two functions are to handle adding/deleting items on the 821fed06968SJulian Elischer * exit callout list 822e0d898b4SJulian Elischer * 823e0d898b4SJulian Elischer * at_exit(): 824e0d898b4SJulian Elischer * Take the arguments given and put them onto the exit callout list, 825fed06968SJulian Elischer * However first make sure that it's not already there. 826fed06968SJulian Elischer * returns 0 on success. 827fed06968SJulian Elischer */ 82893efcae8SPoul-Henning Kamp 829fed06968SJulian Elischer int 830eb776aeaSBruce Evans at_exit(function) 831eb776aeaSBruce Evans exitlist_fn function; 832fed06968SJulian Elischer { 83393efcae8SPoul-Henning Kamp struct exitlist *ep; 834e0d898b4SJulian Elischer 83593efcae8SPoul-Henning Kamp #ifdef INVARIANTS 836e0d898b4SJulian Elischer /* Be noisy if the programmer has lost track of things */ 837e0d898b4SJulian Elischer if (rm_at_exit(function)) 83893efcae8SPoul-Henning Kamp printf("WARNING: exit callout entry (%p) already present\n", 83993efcae8SPoul-Henning Kamp function); 84093efcae8SPoul-Henning Kamp #endif 84193efcae8SPoul-Henning Kamp ep = malloc(sizeof(*ep), M_ATEXIT, M_NOWAIT); 842e0d898b4SJulian Elischer if (ep == NULL) 843e0d898b4SJulian Elischer return (ENOMEM); 844fed06968SJulian Elischer ep->function = function; 84593efcae8SPoul-Henning Kamp TAILQ_INSERT_TAIL(&exit_list, ep, next); 846e0d898b4SJulian Elischer return (0); 847fed06968SJulian Elischer } 84893efcae8SPoul-Henning Kamp 849fed06968SJulian Elischer /* 85093efcae8SPoul-Henning Kamp * Scan the exit callout list for the given item and remove it. 85193efcae8SPoul-Henning Kamp * Returns the number of items removed (0 or 1) 852fed06968SJulian Elischer */ 853fed06968SJulian Elischer int 854eb776aeaSBruce Evans rm_at_exit(function) 855eb776aeaSBruce Evans exitlist_fn function; 856fed06968SJulian Elischer { 85793efcae8SPoul-Henning Kamp struct exitlist *ep; 858fed06968SJulian Elischer 85993efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &exit_list, next) { 860fed06968SJulian Elischer if (ep->function == function) { 86193efcae8SPoul-Henning Kamp TAILQ_REMOVE(&exit_list, ep, next); 86293efcae8SPoul-Henning Kamp free(ep, M_ATEXIT); 86393efcae8SPoul-Henning Kamp return (1); 864fed06968SJulian Elischer } 865fed06968SJulian Elischer } 86693efcae8SPoul-Henning Kamp return (0); 867fed06968SJulian Elischer } 868