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" 44db6a20e2SGarrett Wollman 45df8bae1dSRodney W. Grimes #include <sys/param.h> 46df8bae1dSRodney W. Grimes #include <sys/systm.h> 475fdb8324SBruce Evans #include <sys/sysproto.h> 481c5bb3eaSPeter Wemm #include <sys/kernel.h> 49a1c995b6SPoul-Henning Kamp #include <sys/malloc.h> 50f34fa851SJohn Baldwin #include <sys/lock.h> 5135e0e5b3SJohn Baldwin #include <sys/mutex.h> 52df8bae1dSRodney W. Grimes #include <sys/proc.h> 532a024a2bSSean Eric Fagan #include <sys/pioctl.h> 54df8bae1dSRodney W. Grimes #include <sys/tty.h> 55df8bae1dSRodney W. Grimes #include <sys/wait.h> 56eb30c1c0SPeter Wemm #include <sys/vmmeter.h> 577a6b989bSJohn Baldwin #include <sys/vnode.h> 58df8bae1dSRodney W. Grimes #include <sys/resourcevar.h> 59797f2d22SPoul-Henning Kamp #include <sys/signalvar.h> 601005a129SJohn Baldwin #include <sys/sx.h> 61df8bae1dSRodney W. Grimes #include <sys/ptrace.h> 627c409b8aSJeffrey Hsu #include <sys/acct.h> /* for acct_process() function prototype */ 63797f2d22SPoul-Henning Kamp #include <sys/filedesc.h> 64780dc5a8SPeter Wemm #include <sys/shm.h> 65780dc5a8SPeter Wemm #include <sys/sem.h> 6675c13541SPoul-Henning Kamp #include <sys/jail.h> 676c84de02SJohn Baldwin #ifdef KTRACE 686c84de02SJohn Baldwin #include <sys/ktrace.h> 696c84de02SJohn Baldwin #endif 70780dc5a8SPeter Wemm 71df8bae1dSRodney W. Grimes #include <vm/vm.h> 72eb30c1c0SPeter Wemm #include <vm/vm_extern.h> 737a6b989bSJohn Baldwin #include <vm/vm_param.h> 74efeaf95aSDavid Greenman #include <vm/pmap.h> 75efeaf95aSDavid Greenman #include <vm/vm_map.h> 76c897b813SJeff Roberson #include <vm/uma.h> 77dc9c271aSJulian Elischer #include <sys/user.h> 78df8bae1dSRodney W. Grimes 79ba198b1cSMark Newton /* Required to be non-static for SysVR4 emulator */ 8069a6f20bSMark Newton MALLOC_DEFINE(M_ZOMBIE, "zombie", "zombie proc status"); 8155166637SPoul-Henning Kamp 8293efcae8SPoul-Henning Kamp static MALLOC_DEFINE(M_ATEXIT, "atexit", "atexit callback"); 8393efcae8SPoul-Henning Kamp 844d77a549SAlfred Perlstein static int wait1(struct thread *, struct wait_args *, int); 855fdb8324SBruce Evans 86df8bae1dSRodney W. Grimes /* 87fed06968SJulian Elischer * callout list for things to do at exit time 88fed06968SJulian Elischer */ 8993efcae8SPoul-Henning Kamp struct exitlist { 90fed06968SJulian Elischer exitlist_fn function; 91e3975643SJake Burkholder TAILQ_ENTRY(exitlist) next; 9293efcae8SPoul-Henning Kamp }; 93fed06968SJulian Elischer 94e3975643SJake Burkholder TAILQ_HEAD(exit_list_head, exitlist); 9593efcae8SPoul-Henning Kamp static struct exit_list_head exit_list = TAILQ_HEAD_INITIALIZER(exit_list); 96fed06968SJulian Elischer 97fed06968SJulian Elischer /* 98df8bae1dSRodney W. Grimes * exit -- 99df8bae1dSRodney W. Grimes * Death of process. 100234216efSMatthew Dillon * 101234216efSMatthew Dillon * MPSAFE 102df8bae1dSRodney W. Grimes */ 103fc0b1dbfSBruce Evans void 104b40ce416SJulian Elischer sys_exit(td, uap) 105b40ce416SJulian Elischer struct thread *td; 106ac2b067bSPeter Wemm struct sys_exit_args /* { 1075fdb8324SBruce Evans int rval; 1085fdb8324SBruce Evans } */ *uap; 109df8bae1dSRodney W. Grimes { 110b40ce416SJulian Elischer 111234216efSMatthew Dillon mtx_lock(&Giant); 112b40ce416SJulian Elischer exit1(td, W_EXITCODE(uap->rval, 0)); 113df8bae1dSRodney W. Grimes /* NOTREACHED */ 114df8bae1dSRodney W. Grimes } 115df8bae1dSRodney W. Grimes 116df8bae1dSRodney W. Grimes /* 117df8bae1dSRodney W. Grimes * Exit: deallocate address space and other resources, change proc state 118df8bae1dSRodney W. Grimes * to zombie, and unlink proc from allproc and parent's lists. Save exit 119df8bae1dSRodney W. Grimes * status and rusage for wait(). Check for child processes and orphan them. 120df8bae1dSRodney W. Grimes */ 121fc0b1dbfSBruce Evans void 122b40ce416SJulian Elischer exit1(td, rv) 123b40ce416SJulian Elischer register struct thread *td; 124df8bae1dSRodney W. Grimes int rv; 125df8bae1dSRodney W. Grimes { 126276c5169SJohn Baldwin struct exitlist *ep; 127276c5169SJohn Baldwin struct proc *p, *nq, *q; 128276c5169SJohn Baldwin struct tty *tp; 129276c5169SJohn Baldwin struct vnode *ttyvp; 130df8bae1dSRodney W. Grimes register struct vmspace *vm; 13179deba82SMatthew Dillon struct vnode *vtmp; 132d7aadbf9SJohn Baldwin #ifdef KTRACE 133d7aadbf9SJohn Baldwin struct vnode *tracevp; 134d7aadbf9SJohn Baldwin #endif 135df8bae1dSRodney W. Grimes 1360cddd8f0SMatthew Dillon GIANT_REQUIRED; 1370cddd8f0SMatthew Dillon 138276c5169SJohn Baldwin p = td->td_proc; 139e746d950SJohn Baldwin if (p == initproc) { 1405f7bd355SPoul-Henning Kamp printf("init died (signal %d, exit %d)\n", 141df8bae1dSRodney W. Grimes WTERMSIG(rv), WEXITSTATUS(rv)); 1425f7bd355SPoul-Henning Kamp panic("Going nowhere without my init!"); 1435f7bd355SPoul-Henning Kamp } 1442c1011f7SJohn Dyson 1457a6b989bSJohn Baldwin /* 1467a6b989bSJohn Baldwin * XXXXKSE: MUST abort all other threads before proceeding past here. 1477a6b989bSJohn Baldwin */ 148b40ce416SJulian Elischer 1497a6b989bSJohn Baldwin /* Are we a task leader? */ 150a914fb6bSJohn Baldwin PROC_LOCK(p); 1512c1011f7SJohn Dyson if (p == p->p_leader) { 1522c1011f7SJohn Dyson q = p->p_peers; 153776e0b36SJohn Baldwin while (q != NULL) { 154776e0b36SJohn Baldwin PROC_LOCK(q); 155776e0b36SJohn Baldwin psignal(q, SIGKILL); 156776e0b36SJohn Baldwin PROC_UNLOCK(q); 1572c1011f7SJohn Dyson q = q->p_peers; 1582c1011f7SJohn Dyson } 15979fc0bf4SMike Smith while (p->p_peers) 160a914fb6bSJohn Baldwin msleep((caddr_t)p, &p->p_mtx, PWAIT, "exit1", 0); 1612c1011f7SJohn Dyson } 162a914fb6bSJohn Baldwin PROC_UNLOCK(p); 1632c1011f7SJohn Dyson 164df8bae1dSRodney W. Grimes #ifdef PGINPROF 165df8bae1dSRodney W. Grimes vmsizmon(); 166df8bae1dSRodney W. Grimes #endif 1672a024a2bSSean Eric Fagan STOPEVENT(p, S_EXIT, rv); 16889361835SSean Eric Fagan wakeup(&p->p_stype); /* Wakeup anyone in procfs' PIOCWAIT */ 1692a024a2bSSean Eric Fagan 170fed06968SJulian Elischer /* 171e9189611SPeter Wemm * Check if any loadable modules need anything done at process exit. 172fed06968SJulian Elischer * e.g. SYSV IPC stuff 173fed06968SJulian Elischer * XXX what if one of these generates an error? 174fed06968SJulian Elischer */ 17593efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &exit_list, next) 176fed06968SJulian Elischer (*ep->function)(p); 177fed06968SJulian Elischer 178df8bae1dSRodney W. Grimes stopprofclock(p); 179a914fb6bSJohn Baldwin 180df8bae1dSRodney W. Grimes MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 181df8bae1dSRodney W. Grimes M_ZOMBIE, M_WAITOK); 182df8bae1dSRodney W. Grimes /* 183df8bae1dSRodney W. Grimes * If parent is waiting for us to exit or exec, 184df8bae1dSRodney W. Grimes * P_PPWAIT is set; we will wakeup the parent below. 185df8bae1dSRodney W. Grimes */ 186a914fb6bSJohn Baldwin PROC_LOCK(p); 187df8bae1dSRodney W. Grimes p->p_flag &= ~(P_TRACED | P_PPWAIT); 188df8bae1dSRodney W. Grimes p->p_flag |= P_WEXIT; 1892c42a146SMarcel Moolenaar SIGEMPTYSET(p->p_siglist); 190a914fb6bSJohn Baldwin PROC_UNLOCK(p); 1914cf41af3SPoul-Henning Kamp if (timevalisset(&p->p_realtimer.it_value)) 1924f559836SJake Burkholder callout_stop(&p->p_itcallout); 193df8bae1dSRodney W. Grimes 194df8bae1dSRodney W. Grimes /* 195831d27a9SDon Lewis * Reset any sigio structures pointing to us as a result of 196831d27a9SDon Lewis * F_SETOWN with our pid. 197831d27a9SDon Lewis */ 198831d27a9SDon Lewis funsetownlst(&p->p_sigiolst); 199831d27a9SDon Lewis 200831d27a9SDon Lewis /* 201df8bae1dSRodney W. Grimes * Close open files and release open-file table. 202df8bae1dSRodney W. Grimes * This may block! 203df8bae1dSRodney W. Grimes */ 20448810023SJulian Elischer fdfree(td); /* XXXKSE *//* may not be the one in proc */ 205df8bae1dSRodney W. Grimes 206a914fb6bSJohn Baldwin /* 207a914fb6bSJohn Baldwin * Remove ourself from our leader's peer list and wake our leader. 208a914fb6bSJohn Baldwin */ 209776e0b36SJohn Baldwin PROC_LOCK(p->p_leader); 21079fc0bf4SMike Smith if (p->p_leader->p_peers) { 21179fc0bf4SMike Smith q = p->p_leader; 21279fc0bf4SMike Smith while (q->p_peers != p) 21379fc0bf4SMike Smith q = q->p_peers; 21479fc0bf4SMike Smith q->p_peers = p->p_peers; 21579fc0bf4SMike Smith wakeup((caddr_t)p->p_leader); 21679fc0bf4SMike Smith } 217776e0b36SJohn Baldwin PROC_UNLOCK(p->p_leader); 21879fc0bf4SMike Smith 219df8bae1dSRodney W. Grimes /* The next two chunks should probably be moved to vmspace_exit. */ 220df8bae1dSRodney W. Grimes vm = p->p_vmspace; 221df8bae1dSRodney W. Grimes /* 222df8bae1dSRodney W. Grimes * Release user portion of address space. 223df8bae1dSRodney W. Grimes * This releases references to vnodes, 224df8bae1dSRodney W. Grimes * which could cause I/O if the file has been unlinked. 225df8bae1dSRodney W. Grimes * Need to do this early enough that we can still sleep. 226df8bae1dSRodney W. Grimes * Can't free the entire vmspace as the kernel stack 227df8bae1dSRodney W. Grimes * may be mapped within that space also. 228df8bae1dSRodney W. Grimes */ 229582ec34cSAlfred Perlstein if (--vm->vm_refcnt == 0) { 230a2a1c95cSPeter Wemm if (vm->vm_shm) 231a2a1c95cSPeter Wemm shmexit(p); 232b1028ad1SLuoqi Chen pmap_remove_pages(vmspace_pmap(vm), VM_MIN_ADDRESS, 2339d3fbbb5SJohn Dyson VM_MAXUSER_ADDRESS); 23467bf6868SJohn Dyson (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, 23567bf6868SJohn Dyson VM_MAXUSER_ADDRESS); 236582ec34cSAlfred Perlstein vm->vm_freer = p; 2379d3fbbb5SJohn Dyson } 238df8bae1dSRodney W. Grimes 239ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 240df8bae1dSRodney W. Grimes if (SESS_LEADER(p)) { 241f591779bSSeigo Tanimura register struct session *sp; 242df8bae1dSRodney W. Grimes 243f591779bSSeigo Tanimura sp = p->p_session; 244df8bae1dSRodney W. Grimes if (sp->s_ttyvp) { 245df8bae1dSRodney W. Grimes /* 246df8bae1dSRodney W. Grimes * Controlling process. 247df8bae1dSRodney W. Grimes * Signal foreground pgrp, 248df8bae1dSRodney W. Grimes * drain controlling terminal 249df8bae1dSRodney W. Grimes * and revoke access to controlling terminal. 250df8bae1dSRodney W. Grimes */ 251dd45d8adSJulian Elischer if (sp->s_ttyp && (sp->s_ttyp->t_session == sp)) { 252f591779bSSeigo Tanimura tp = sp->s_ttyp; 253f591779bSSeigo Tanimura if (sp->s_ttyp->t_pgrp) { 254f591779bSSeigo Tanimura PGRP_LOCK(sp->s_ttyp->t_pgrp); 255df8bae1dSRodney W. Grimes pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 256f591779bSSeigo Tanimura PGRP_UNLOCK(sp->s_ttyp->t_pgrp); 257f591779bSSeigo Tanimura } 258f591779bSSeigo Tanimura /* XXX tp should be locked. */ 259ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 260f591779bSSeigo Tanimura (void) ttywait(tp); 261ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 262df8bae1dSRodney W. Grimes /* 263df8bae1dSRodney W. Grimes * The tty could have been revoked 264df8bae1dSRodney W. Grimes * if we blocked. 265df8bae1dSRodney W. Grimes */ 266f591779bSSeigo Tanimura if (sp->s_ttyvp) { 267f591779bSSeigo Tanimura ttyvp = sp->s_ttyvp; 268f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 269df8bae1dSRodney W. Grimes sp->s_ttyvp = NULL; 270f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 271ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 272f591779bSSeigo Tanimura VOP_REVOKE(ttyvp, REVOKEALL); 273f591779bSSeigo Tanimura vrele(ttyvp); 274ea97757aSJohn Baldwin sx_xlock(&proctree_lock); 275f591779bSSeigo Tanimura } 276f591779bSSeigo Tanimura } 277f591779bSSeigo Tanimura if (sp->s_ttyvp) { 278f591779bSSeigo Tanimura ttyvp = sp->s_ttyvp; 279f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 280f591779bSSeigo Tanimura sp->s_ttyvp = NULL; 281f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 282f591779bSSeigo Tanimura vrele(ttyvp); 283f591779bSSeigo Tanimura } 284df8bae1dSRodney W. Grimes /* 285df8bae1dSRodney W. Grimes * s_ttyp is not zero'd; we use this to indicate 286df8bae1dSRodney W. Grimes * that the session once had a controlling terminal. 287df8bae1dSRodney W. Grimes * (for logging and informational purposes) 288df8bae1dSRodney W. Grimes */ 289df8bae1dSRodney W. Grimes } 290f591779bSSeigo Tanimura SESS_LOCK(p->p_session); 291df8bae1dSRodney W. Grimes sp->s_leader = NULL; 292f591779bSSeigo Tanimura SESS_UNLOCK(p->p_session); 293f591779bSSeigo Tanimura } 294df8bae1dSRodney W. Grimes fixjobc(p, p->p_pgrp, 0); 295ea97757aSJohn Baldwin sx_xunlock(&proctree_lock); 296b40ce416SJulian Elischer (void)acct_process(td); 297df8bae1dSRodney W. Grimes #ifdef KTRACE 298df8bae1dSRodney W. Grimes /* 299df8bae1dSRodney W. Grimes * release trace file 300df8bae1dSRodney W. Grimes */ 301d7aadbf9SJohn Baldwin PROC_LOCK(p); 3026c84de02SJohn Baldwin mtx_lock(&ktrace_mtx); 303df8bae1dSRodney W. Grimes p->p_traceflag = 0; /* don't trace the vrele() */ 304d7aadbf9SJohn Baldwin tracevp = p->p_tracep; 30579deba82SMatthew Dillon p->p_tracep = NULL; 3066c84de02SJohn Baldwin mtx_unlock(&ktrace_mtx); 307d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 308d7aadbf9SJohn Baldwin if (tracevp != NULL) 309d7aadbf9SJohn Baldwin vrele(tracevp); 310df8bae1dSRodney W. Grimes #endif 311df8bae1dSRodney W. Grimes /* 312ee42d0a9SDavid Malone * Release reference to text vnode 313ee42d0a9SDavid Malone */ 314ee42d0a9SDavid Malone if ((vtmp = p->p_textvp) != NULL) { 315ee42d0a9SDavid Malone p->p_textvp = NULL; 316ee42d0a9SDavid Malone vrele(vtmp); 317ee42d0a9SDavid Malone } 318ee42d0a9SDavid Malone 319ee42d0a9SDavid Malone /* 320d7aadbf9SJohn Baldwin * Release our limits structure. 321d7aadbf9SJohn Baldwin */ 322d7aadbf9SJohn Baldwin mtx_assert(&Giant, MA_OWNED); 323d7aadbf9SJohn Baldwin if (--p->p_limit->p_refcnt == 0) { 324d7aadbf9SJohn Baldwin FREE(p->p_limit, M_SUBPROC); 325d7aadbf9SJohn Baldwin p->p_limit = NULL; 326d7aadbf9SJohn Baldwin } 327d7aadbf9SJohn Baldwin 328d7aadbf9SJohn Baldwin /* 329d7aadbf9SJohn Baldwin * Release this thread's reference to the ucred. The actual proc 330d7aadbf9SJohn Baldwin * reference will stay around until the proc is harvested by 331d7aadbf9SJohn Baldwin * wait(). At this point the ucred is immutable (no other threads 332d7aadbf9SJohn Baldwin * from this proc are around that can change it) so we leave the 333d7aadbf9SJohn Baldwin * per-thread ucred pointer intact in case it is needed although 334d7aadbf9SJohn Baldwin * in theory nothing should be using it at this point. 335d7aadbf9SJohn Baldwin */ 336d7aadbf9SJohn Baldwin crfree(td->td_ucred); 337d7aadbf9SJohn Baldwin 338d7aadbf9SJohn Baldwin /* 339df8bae1dSRodney W. Grimes * Remove proc from allproc queue and pidhash chain. 340df8bae1dSRodney W. Grimes * Place onto zombproc. Unlink from parent's child list. 341df8bae1dSRodney W. Grimes */ 3421005a129SJohn Baldwin sx_xlock(&allproc_lock); 343b75356e1SJeffrey Hsu LIST_REMOVE(p, p_list); 344b75356e1SJeffrey Hsu LIST_INSERT_HEAD(&zombproc, p, p_list); 345b75356e1SJeffrey Hsu LIST_REMOVE(p, p_hash); 3461005a129SJohn Baldwin sx_xunlock(&allproc_lock); 347df8bae1dSRodney W. Grimes 3481005a129SJohn Baldwin sx_xlock(&proctree_lock); 3492e3c8fcbSPoul-Henning Kamp q = LIST_FIRST(&p->p_children); 350a914fb6bSJohn Baldwin if (q != NULL) /* only need this if any child is S_ZOMB */ 351df8bae1dSRodney W. Grimes wakeup((caddr_t) initproc); 352a914fb6bSJohn Baldwin for (; q != NULL; q = nq) { 3532e3c8fcbSPoul-Henning Kamp nq = LIST_NEXT(q, p_sibling); 354a914fb6bSJohn Baldwin PROC_LOCK(q); 355c65437a3SJohn Baldwin proc_reparent(q, initproc); 3564ac9ae70SJulian Elischer q->p_sigparent = SIGCHLD; 357df8bae1dSRodney W. Grimes /* 358df8bae1dSRodney W. Grimes * Traced processes are killed 359df8bae1dSRodney W. Grimes * since their existence means someone is screwing up. 360df8bae1dSRodney W. Grimes */ 361df8bae1dSRodney W. Grimes if (q->p_flag & P_TRACED) { 362df8bae1dSRodney W. Grimes q->p_flag &= ~P_TRACED; 363df8bae1dSRodney W. Grimes psignal(q, SIGKILL); 364c65437a3SJohn Baldwin } 365a914fb6bSJohn Baldwin PROC_UNLOCK(q); 366df8bae1dSRodney W. Grimes } 367df8bae1dSRodney W. Grimes 368df8bae1dSRodney W. Grimes /* 369df8bae1dSRodney W. Grimes * Save exit status and final rusage info, adding in child rusage 370df8bae1dSRodney W. Grimes * info and self times. 371df8bae1dSRodney W. Grimes */ 372d7aadbf9SJohn Baldwin PROC_LOCK(p); 373df8bae1dSRodney W. Grimes p->p_xstat = rv; 374df8bae1dSRodney W. Grimes *p->p_ru = p->p_stats->p_ru; 3759ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 376df8bae1dSRodney W. Grimes calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL); 3779ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 378df8bae1dSRodney W. Grimes ruadd(p->p_ru, &p->p_stats->p_cru); 379df8bae1dSRodney W. Grimes 380df8bae1dSRodney W. Grimes /* 3817a6b989bSJohn Baldwin * Notify interested parties of our demise. 382cb679c38SJonathan Lemon */ 383a274d19bSBrian Feldman KNOTE(&p->p_klist, NOTE_EXIT); 384cb679c38SJonathan Lemon 385cb679c38SJonathan Lemon /* 386645682fdSLuoqi Chen * Notify parent that we're gone. If parent has the PS_NOCLDWAIT 387ba1551caSIan Dowse * flag set, or if the handler is set to SIG_IGN, notify process 388ba1551caSIan Dowse * 1 instead (and hope it will handle this situation). 389df8bae1dSRodney W. Grimes */ 390d7aadbf9SJohn Baldwin PROC_LOCK(p->p_pptr); 391ba1551caSIan Dowse if (p->p_pptr->p_procsig->ps_flag & (PS_NOCLDWAIT | PS_CLDSIGIGN)) { 392276c5169SJohn Baldwin struct proc *pp; 393276c5169SJohn Baldwin 394276c5169SJohn Baldwin pp = p->p_pptr; 395f591779bSSeigo Tanimura PROC_UNLOCK(pp); 396245f17d4SJoerg Wunsch proc_reparent(p, initproc); 397f591779bSSeigo Tanimura PROC_LOCK(p->p_pptr); 398245f17d4SJoerg Wunsch /* 399245f17d4SJoerg Wunsch * If this was the last child of our parent, notify 400245f17d4SJoerg Wunsch * parent, so in case he was wait(2)ing, he will 401245f17d4SJoerg Wunsch * continue. 402245f17d4SJoerg Wunsch */ 403245f17d4SJoerg Wunsch if (LIST_EMPTY(&pp->p_children)) 404245f17d4SJoerg Wunsch wakeup((caddr_t)pp); 405245f17d4SJoerg Wunsch } 406245f17d4SJoerg Wunsch 407c65437a3SJohn Baldwin if (p->p_sigparent && p->p_pptr != initproc) 4086626c604SJulian Elischer psignal(p->p_pptr, p->p_sigparent); 409c65437a3SJohn Baldwin else 4106626c604SJulian Elischer psignal(p->p_pptr, SIGCHLD); 411c65437a3SJohn Baldwin PROC_UNLOCK(p->p_pptr); 412776e0b36SJohn Baldwin 413776e0b36SJohn Baldwin /* 414776e0b36SJohn Baldwin * If this is a kthread, then wakeup anyone waiting for it to exit. 415776e0b36SJohn Baldwin */ 416776e0b36SJohn Baldwin if (p->p_flag & P_KTHREAD) 417776e0b36SJohn Baldwin wakeup((caddr_t)p); 418c65437a3SJohn Baldwin PROC_UNLOCK(p); 4198e2e767bSJohn Baldwin 4208e2e767bSJohn Baldwin /* 421df8bae1dSRodney W. Grimes * Finally, call machine-dependent code to release the remaining 422df8bae1dSRodney W. Grimes * resources including address space, the kernel stack and pcb. 423582ec34cSAlfred Perlstein * The address space is released by "vmspace_exitfree(p)" in 424582ec34cSAlfred Perlstein * vm_waitproc(). 425df8bae1dSRodney W. Grimes */ 426b40ce416SJulian Elischer cpu_exit(td); 427eb30c1c0SPeter Wemm 428eb30c1c0SPeter Wemm PROC_LOCK(p); 429d7aadbf9SJohn Baldwin PROC_LOCK(p->p_pptr); 430d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 431eb30c1c0SPeter Wemm mtx_lock_spin(&sched_lock); 432eb30c1c0SPeter Wemm while (mtx_owned(&Giant)) 433c86b6ff5SJohn Baldwin mtx_unlock(&Giant); 434eb30c1c0SPeter Wemm 435eb30c1c0SPeter Wemm /* 436eb30c1c0SPeter Wemm * We have to wait until after releasing all locks before 437eb30c1c0SPeter Wemm * changing p_stat. If we block on a mutex then we will be 438eb30c1c0SPeter Wemm * back at SRUN when we resume and our parent will never 439eb30c1c0SPeter Wemm * harvest us. 440eb30c1c0SPeter Wemm */ 441eb30c1c0SPeter Wemm p->p_stat = SZOMB; 442eb30c1c0SPeter Wemm 443eb30c1c0SPeter Wemm wakeup(p->p_pptr); 444d7aadbf9SJohn Baldwin PROC_UNLOCK(p->p_pptr); 445c86b6ff5SJohn Baldwin PROC_UNLOCK(p); 446eb30c1c0SPeter Wemm 447eb30c1c0SPeter Wemm cnt.v_swtch++; 448d7aadbf9SJohn Baldwin binuptime(PCPU_PTR(switchtime)); 449d7aadbf9SJohn Baldwin PCPU_SET(switchticks, ticks); 450d7aadbf9SJohn Baldwin 451eb30c1c0SPeter Wemm cpu_throw(); 452eb30c1c0SPeter Wemm panic("exit1"); 453df8bae1dSRodney W. Grimes } 454df8bae1dSRodney W. Grimes 455b2f9e8b1SBruce Evans #ifdef COMPAT_43 456234216efSMatthew Dillon /* 4577a6b989bSJohn Baldwin * MPSAFE. The dirty work is handled by wait1(). 458234216efSMatthew Dillon */ 45926f9a767SRodney W. Grimes int 460b40ce416SJulian Elischer owait(td, uap) 461b40ce416SJulian Elischer struct thread *td; 4625fdb8324SBruce Evans register struct owait_args /* { 4635fdb8324SBruce Evans int dummy; 4645fdb8324SBruce Evans } */ *uap; 465df8bae1dSRodney W. Grimes { 46693c9414eSSteven Wallace struct wait_args w; 467df8bae1dSRodney W. Grimes 46893c9414eSSteven Wallace w.options = 0; 46993c9414eSSteven Wallace w.rusage = NULL; 47093c9414eSSteven Wallace w.pid = WAIT_ANY; 47193c9414eSSteven Wallace w.status = NULL; 472b40ce416SJulian Elischer return (wait1(td, &w, 1)); 473df8bae1dSRodney W. Grimes } 474b2f9e8b1SBruce Evans #endif /* COMPAT_43 */ 475df8bae1dSRodney W. Grimes 476234216efSMatthew Dillon /* 4777a6b989bSJohn Baldwin * MPSAFE. The dirty work is handled by wait1(). 478234216efSMatthew Dillon */ 47926f9a767SRodney W. Grimes int 480b40ce416SJulian Elischer wait4(td, uap) 481b40ce416SJulian Elischer struct thread *td; 482df8bae1dSRodney W. Grimes struct wait_args *uap; 483df8bae1dSRodney W. Grimes { 484b40ce416SJulian Elischer 485b40ce416SJulian Elischer return (wait1(td, uap, 0)); 486df8bae1dSRodney W. Grimes } 487df8bae1dSRodney W. Grimes 488234216efSMatthew Dillon /* 489234216efSMatthew Dillon * MPSAFE 490234216efSMatthew Dillon */ 49193c9414eSSteven Wallace static int 492b40ce416SJulian Elischer wait1(td, uap, compat) 493b40ce416SJulian Elischer register struct thread *td; 4945fdb8324SBruce Evans register struct wait_args /* { 4955fdb8324SBruce Evans int pid; 4965fdb8324SBruce Evans int *status; 4975fdb8324SBruce Evans int options; 4985fdb8324SBruce Evans struct rusage *rusage; 4995fdb8324SBruce Evans } */ *uap; 50093c9414eSSteven Wallace int compat; 501df8bae1dSRodney W. Grimes { 502276c5169SJohn Baldwin struct rusage ru; 503df8bae1dSRodney W. Grimes register int nfound; 504276c5169SJohn Baldwin register struct proc *p, *q, *t; 505f23c6d68SSteven Wallace int status, error; 506df8bae1dSRodney W. Grimes 507b40ce416SJulian Elischer q = td->td_proc; 508f591779bSSeigo Tanimura if (uap->pid == 0) { 509f591779bSSeigo Tanimura PROC_LOCK(q); 510df8bae1dSRodney W. Grimes uap->pid = -q->p_pgid; 511f591779bSSeigo Tanimura PROC_UNLOCK(q); 512f591779bSSeigo Tanimura } 5136ee093fbSMike Barcroft if (uap->options &~ (WUNTRACED|WNOHANG|WCONTINUED|WLINUXCLONE)) 5146dc958b9SJohn Baldwin return (EINVAL); 5156dc958b9SJohn Baldwin mtx_lock(&Giant); 516df8bae1dSRodney W. Grimes loop: 517df8bae1dSRodney W. Grimes nfound = 0; 518d7aadbf9SJohn Baldwin sx_xlock(&proctree_lock); 5192e3c8fcbSPoul-Henning Kamp LIST_FOREACH(p, &q->p_children, p_sibling) { 520f591779bSSeigo Tanimura PROC_LOCK(p); 521df8bae1dSRodney W. Grimes if (uap->pid != WAIT_ANY && 522f591779bSSeigo Tanimura p->p_pid != uap->pid && p->p_pgid != -uap->pid) { 523f591779bSSeigo Tanimura PROC_UNLOCK(p); 524df8bae1dSRodney W. Grimes continue; 525f591779bSSeigo Tanimura } 5264ac9ae70SJulian Elischer 5271156bc4dSJake Burkholder /* 5281156bc4dSJake Burkholder * This special case handles a kthread spawned by linux_clone 5291156bc4dSJake Burkholder * (see linux_misc.c). The linux_wait4 and linux_waitpid 5301156bc4dSJake Burkholder * functions need to be able to distinguish between waiting 5311156bc4dSJake Burkholder * on a process and waiting on a thread. It is a thread if 5321156bc4dSJake Burkholder * p_sigparent is not SIGCHLD, and the WLINUXCLONE option 5331156bc4dSJake Burkholder * signifies we want to wait for threads and not processes. 5344ac9ae70SJulian Elischer */ 5351156bc4dSJake Burkholder if ((p->p_sigparent != SIGCHLD) ^ 536a914fb6bSJohn Baldwin ((uap->options & WLINUXCLONE) != 0)) { 537a914fb6bSJohn Baldwin PROC_UNLOCK(p); 5384ac9ae70SJulian Elischer continue; 539a914fb6bSJohn Baldwin } 5404ac9ae70SJulian Elischer 541df8bae1dSRodney W. Grimes nfound++; 542df8bae1dSRodney W. Grimes if (p->p_stat == SZOMB) { 543b40ce416SJulian Elischer /* 544b40ce416SJulian Elischer * charge childs scheduling cpu usage to parent 545b40ce416SJulian Elischer * XXXKSE assume only one thread & kse & ksegrp 546b40ce416SJulian Elischer * keep estcpu in each ksegrp 547b40ce416SJulian Elischer * so charge it to the ksegrp that did the wait 548b40ce416SJulian Elischer * since process estcpu is sum of all ksegrps, 549b40ce416SJulian Elischer * this is strictly as expected. 550b40ce416SJulian Elischer * Assume that the child process aggregated all 551b40ce416SJulian Elischer * tke estcpu into the 'build-in' ksegrp. 552b40ce416SJulian Elischer * XXXKSE 553b40ce416SJulian Elischer */ 554b40ce416SJulian Elischer if (curthread->td_proc->p_pid != 1) { 555d7aadbf9SJohn Baldwin mtx_lock_spin(&sched_lock); 556b40ce416SJulian Elischer curthread->td_ksegrp->kg_estcpu = 557b40ce416SJulian Elischer ESTCPULIM(curthread->td_ksegrp->kg_estcpu + 558b40ce416SJulian Elischer p->p_ksegrp.kg_estcpu); 559c65437a3SJohn Baldwin mtx_unlock_spin(&sched_lock); 560d7aadbf9SJohn Baldwin } 561c65437a3SJohn Baldwin 562b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 563b2f9e8b1SBruce Evans #ifdef COMPAT_43 56493c9414eSSteven Wallace if (compat) 565b40ce416SJulian Elischer td->td_retval[1] = p->p_xstat; 566df8bae1dSRodney W. Grimes else 567df8bae1dSRodney W. Grimes #endif 568df8bae1dSRodney W. Grimes if (uap->status) { 569df8bae1dSRodney W. Grimes status = p->p_xstat; /* convert to int */ 570d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 571bb56ec4aSPoul-Henning Kamp if ((error = copyout((caddr_t)&status, 572234216efSMatthew Dillon (caddr_t)uap->status, sizeof(status)))) { 573d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 574d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 575d7aadbf9SJohn Baldwin return (error); 576234216efSMatthew Dillon } 577d7aadbf9SJohn Baldwin PROC_LOCK(p); 578df8bae1dSRodney W. Grimes } 579d7aadbf9SJohn Baldwin if (uap->rusage) { 580d7aadbf9SJohn Baldwin bcopy(p->p_ru, &ru, sizeof(ru)); 581d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 582d7aadbf9SJohn Baldwin if ((error = copyout((caddr_t)&ru, 583d7aadbf9SJohn Baldwin (caddr_t)uap->rusage, 584d7aadbf9SJohn Baldwin sizeof (struct rusage)))) { 585d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 586d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 587d7aadbf9SJohn Baldwin return (error); 588234216efSMatthew Dillon } 589d7aadbf9SJohn Baldwin } else 590d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 591df8bae1dSRodney W. Grimes /* 592df8bae1dSRodney W. Grimes * If we got the child via a ptrace 'attach', 593df8bae1dSRodney W. Grimes * we need to give it back to the old parent. 594df8bae1dSRodney W. Grimes */ 595d7aadbf9SJohn Baldwin if (p->p_oppid && (t = pfind(p->p_oppid)) != NULL) { 596c65437a3SJohn Baldwin PROC_LOCK(p); 597df8bae1dSRodney W. Grimes p->p_oppid = 0; 598df8bae1dSRodney W. Grimes proc_reparent(p, t); 599c65437a3SJohn Baldwin PROC_UNLOCK(p); 600df8bae1dSRodney W. Grimes psignal(t, SIGCHLD); 60133a9ed9dSJohn Baldwin wakeup((caddr_t)t); 602c65437a3SJohn Baldwin PROC_UNLOCK(t); 6031005a129SJohn Baldwin sx_xunlock(&proctree_lock); 604d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 605d7aadbf9SJohn Baldwin return (0); 606df8bae1dSRodney W. Grimes } 607df8bae1dSRodney W. Grimes /* 608d7aadbf9SJohn Baldwin * Remove other references to this process to ensure 609d7aadbf9SJohn Baldwin * we have an exclusive reference. 610df8bae1dSRodney W. Grimes */ 611ebdc3f1dSSeigo Tanimura leavepgrp(p); 612ebdc3f1dSSeigo Tanimura 613ebdc3f1dSSeigo Tanimura sx_xlock(&allproc_lock); 614ebdc3f1dSSeigo Tanimura LIST_REMOVE(p, p_list); /* off zombproc */ 615ebdc3f1dSSeigo Tanimura sx_xunlock(&allproc_lock); 616ebdc3f1dSSeigo Tanimura 617ebdc3f1dSSeigo Tanimura LIST_REMOVE(p, p_sibling); 618ebdc3f1dSSeigo Tanimura sx_xunlock(&proctree_lock); 619ebdc3f1dSSeigo Tanimura 620ebdc3f1dSSeigo Tanimura /* 621d7aadbf9SJohn Baldwin * As a side effect of this lock, we know that 622d7aadbf9SJohn Baldwin * all other writes to this proc are visible now, so 623d7aadbf9SJohn Baldwin * no more locking is needed for p. 624d7aadbf9SJohn Baldwin */ 625d7aadbf9SJohn Baldwin PROC_LOCK(p); 626d7aadbf9SJohn Baldwin p->p_xstat = 0; /* XXX: why? */ 627d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 628d7aadbf9SJohn Baldwin PROC_LOCK(q); 629d7aadbf9SJohn Baldwin ruadd(&q->p_stats->p_cru, p->p_ru); 630d7aadbf9SJohn Baldwin PROC_UNLOCK(q); 631d7aadbf9SJohn Baldwin FREE(p->p_ru, M_ZOMBIE); 632d7aadbf9SJohn Baldwin p->p_ru = NULL; 633d7aadbf9SJohn Baldwin 634d7aadbf9SJohn Baldwin /* 635d7aadbf9SJohn Baldwin * Decrement the count of procs running with this uid. 636d7aadbf9SJohn Baldwin */ 637d7aadbf9SJohn Baldwin (void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0); 638d7aadbf9SJohn Baldwin 639d7aadbf9SJohn Baldwin /* 640df8bae1dSRodney W. Grimes * Free up credentials. 641df8bae1dSRodney W. Grimes */ 642da654d90SPoul-Henning Kamp crfree(p->p_ucred); 643d7aadbf9SJohn Baldwin p->p_ucred = NULL; /* XXX: why? */ 644df8bae1dSRodney W. Grimes 645df8bae1dSRodney W. Grimes /* 646b9df5231SPoul-Henning Kamp * Remove unused arguments 647b9df5231SPoul-Henning Kamp */ 648d7aadbf9SJohn Baldwin pargs_drop(p->p_args); 649d7aadbf9SJohn Baldwin p->p_args = NULL; 650b9df5231SPoul-Henning Kamp 6516626c604SJulian Elischer if (--p->p_procsig->ps_refcnt == 0) { 652b40ce416SJulian Elischer if (p->p_sigacts != &p->p_uarea->u_sigacts) 653dc9c271aSJulian Elischer FREE(p->p_sigacts, M_SUBPROC); 654dc9c271aSJulian Elischer FREE(p->p_procsig, M_SUBPROC); 6556626c604SJulian Elischer p->p_procsig = NULL; 6566626c604SJulian Elischer } 65788c5ea45SJulian Elischer 658df8bae1dSRodney W. Grimes /* 659eb30c1c0SPeter Wemm * Give vm and machine-dependent layer a chance 660df8bae1dSRodney W. Grimes * to free anything that cpu_exit couldn't 661df8bae1dSRodney W. Grimes * release while still running in process context. 662df8bae1dSRodney W. Grimes */ 663eb30c1c0SPeter Wemm vm_waitproc(p); 6644971f62aSJohn Baldwin mtx_destroy(&p->p_mtx); 665c897b813SJeff Roberson uma_zfree(proc_zone, p); 666d7aadbf9SJohn Baldwin sx_xlock(&allproc_lock); 667df8bae1dSRodney W. Grimes nprocs--; 668d7aadbf9SJohn Baldwin sx_xunlock(&allproc_lock); 669d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 670d7aadbf9SJohn Baldwin return (0); 671df8bae1dSRodney W. Grimes } 672df8bae1dSRodney W. Grimes if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 && 673df8bae1dSRodney W. Grimes (p->p_flag & P_TRACED || uap->options & WUNTRACED)) { 674df8bae1dSRodney W. Grimes p->p_flag |= P_WAITED; 675d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 676b40ce416SJulian Elischer td->td_retval[0] = p->p_pid; 677b2f9e8b1SBruce Evans #ifdef COMPAT_43 67893c9414eSSteven Wallace if (compat) { 679b40ce416SJulian Elischer td->td_retval[1] = W_STOPCODE(p->p_xstat); 680d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 681df8bae1dSRodney W. Grimes error = 0; 682df8bae1dSRodney W. Grimes } else 683df8bae1dSRodney W. Grimes #endif 684df8bae1dSRodney W. Grimes if (uap->status) { 685df8bae1dSRodney W. Grimes status = W_STOPCODE(p->p_xstat); 686d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 687df8bae1dSRodney W. Grimes error = copyout((caddr_t)&status, 688df8bae1dSRodney W. Grimes (caddr_t)uap->status, sizeof(status)); 689d7aadbf9SJohn Baldwin } else { 690a914fb6bSJohn Baldwin PROC_UNLOCK(p); 691234216efSMatthew Dillon error = 0; 692df8bae1dSRodney W. Grimes } 693234216efSMatthew Dillon mtx_unlock(&Giant); 694234216efSMatthew Dillon return (error); 695df8bae1dSRodney W. Grimes } 6966ee093fbSMike Barcroft if (uap->options & WCONTINUED && (p->p_flag & P_CONTINUED)) { 6976ee093fbSMike Barcroft sx_xunlock(&proctree_lock); 6986ee093fbSMike Barcroft td->td_retval[0] = p->p_pid; 6996ee093fbSMike Barcroft p->p_flag &= ~P_CONTINUED; 7006ee093fbSMike Barcroft PROC_UNLOCK(p); 7016ee093fbSMike Barcroft 7026ee093fbSMike Barcroft if (uap->status) { 7036ee093fbSMike Barcroft status = SIGCONT; 7046ee093fbSMike Barcroft error = copyout((caddr_t)&status, 7056ee093fbSMike Barcroft (caddr_t)uap->status, sizeof(status)); 7066ee093fbSMike Barcroft } else 7076ee093fbSMike Barcroft error = 0; 7086ee093fbSMike Barcroft 7096ee093fbSMike Barcroft mtx_unlock(&Giant); 7106ee093fbSMike Barcroft return (error); 7116ee093fbSMike Barcroft } 712d7aadbf9SJohn Baldwin PROC_UNLOCK(p); 713d7aadbf9SJohn Baldwin } 714d7aadbf9SJohn Baldwin if (nfound == 0) { 715d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 716d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 717d7aadbf9SJohn Baldwin return (ECHILD); 718d7aadbf9SJohn Baldwin } 719d7aadbf9SJohn Baldwin if (uap->options & WNOHANG) { 720d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 721d7aadbf9SJohn Baldwin td->td_retval[0] = 0; 722d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 723d7aadbf9SJohn Baldwin return (0); 724d7aadbf9SJohn Baldwin } 725d7aadbf9SJohn Baldwin PROC_LOCK(q); 726d7aadbf9SJohn Baldwin sx_xunlock(&proctree_lock); 727d7aadbf9SJohn Baldwin error = msleep((caddr_t)q, &q->p_mtx, PWAIT | PCATCH, "wait", 0); 728d7aadbf9SJohn Baldwin PROC_UNLOCK(q); 729d7aadbf9SJohn Baldwin if (error) { 730d7aadbf9SJohn Baldwin mtx_unlock(&Giant); 731d7aadbf9SJohn Baldwin return (error); 732d7aadbf9SJohn Baldwin } 733d7aadbf9SJohn Baldwin goto loop; 734d7aadbf9SJohn Baldwin } 735df8bae1dSRodney W. Grimes 736df8bae1dSRodney W. Grimes /* 73798f03f90SJake Burkholder * Make process 'parent' the new parent of process 'child'. 73898f03f90SJake Burkholder * Must be called with an exclusive hold of proctree lock. 739df8bae1dSRodney W. Grimes */ 740df8bae1dSRodney W. Grimes void 741df8bae1dSRodney W. Grimes proc_reparent(child, parent) 742df8bae1dSRodney W. Grimes register struct proc *child; 743df8bae1dSRodney W. Grimes register struct proc *parent; 744df8bae1dSRodney W. Grimes { 745df8bae1dSRodney W. Grimes 7464e5e677bSJohn Baldwin sx_assert(&proctree_lock, SX_XLOCKED); 747c65437a3SJohn Baldwin PROC_LOCK_ASSERT(child, MA_OWNED); 748df8bae1dSRodney W. Grimes if (child->p_pptr == parent) 749df8bae1dSRodney W. Grimes return; 750df8bae1dSRodney W. Grimes 751b75356e1SJeffrey Hsu LIST_REMOVE(child, p_sibling); 752b75356e1SJeffrey Hsu LIST_INSERT_HEAD(&parent->p_children, child, p_sibling); 753df8bae1dSRodney W. Grimes child->p_pptr = parent; 754df8bae1dSRodney W. Grimes } 755fed06968SJulian Elischer 756e0d898b4SJulian Elischer /* 757e0d898b4SJulian Elischer * The next two functions are to handle adding/deleting items on the 758fed06968SJulian Elischer * exit callout list 759e0d898b4SJulian Elischer * 760e0d898b4SJulian Elischer * at_exit(): 761e0d898b4SJulian Elischer * Take the arguments given and put them onto the exit callout list, 762fed06968SJulian Elischer * However first make sure that it's not already there. 763fed06968SJulian Elischer * returns 0 on success. 764fed06968SJulian Elischer */ 76593efcae8SPoul-Henning Kamp 766fed06968SJulian Elischer int 767eb776aeaSBruce Evans at_exit(function) 768eb776aeaSBruce Evans exitlist_fn function; 769fed06968SJulian Elischer { 77093efcae8SPoul-Henning Kamp struct exitlist *ep; 771e0d898b4SJulian Elischer 77293efcae8SPoul-Henning Kamp #ifdef INVARIANTS 773e0d898b4SJulian Elischer /* Be noisy if the programmer has lost track of things */ 774e0d898b4SJulian Elischer if (rm_at_exit(function)) 77593efcae8SPoul-Henning Kamp printf("WARNING: exit callout entry (%p) already present\n", 77693efcae8SPoul-Henning Kamp function); 77793efcae8SPoul-Henning Kamp #endif 77893efcae8SPoul-Henning Kamp ep = malloc(sizeof(*ep), M_ATEXIT, M_NOWAIT); 779e0d898b4SJulian Elischer if (ep == NULL) 780e0d898b4SJulian Elischer return (ENOMEM); 781fed06968SJulian Elischer ep->function = function; 78293efcae8SPoul-Henning Kamp TAILQ_INSERT_TAIL(&exit_list, ep, next); 783e0d898b4SJulian Elischer return (0); 784fed06968SJulian Elischer } 78593efcae8SPoul-Henning Kamp 786fed06968SJulian Elischer /* 78793efcae8SPoul-Henning Kamp * Scan the exit callout list for the given item and remove it. 78893efcae8SPoul-Henning Kamp * Returns the number of items removed (0 or 1) 789fed06968SJulian Elischer */ 790fed06968SJulian Elischer int 791eb776aeaSBruce Evans rm_at_exit(function) 792eb776aeaSBruce Evans exitlist_fn function; 793fed06968SJulian Elischer { 79493efcae8SPoul-Henning Kamp struct exitlist *ep; 795fed06968SJulian Elischer 79693efcae8SPoul-Henning Kamp TAILQ_FOREACH(ep, &exit_list, next) { 797fed06968SJulian Elischer if (ep->function == function) { 79893efcae8SPoul-Henning Kamp TAILQ_REMOVE(&exit_list, ep, next); 79993efcae8SPoul-Henning Kamp free(ep, M_ATEXIT); 80093efcae8SPoul-Henning Kamp return (1); 801fed06968SJulian Elischer } 802fed06968SJulian Elischer } 80393efcae8SPoul-Henning Kamp return (0); 804fed06968SJulian Elischer } 805