kern_exit.c revision 91140
1/* 2 * Copyright (c) 1982, 1986, 1989, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 39 * $FreeBSD: head/sys/kern/kern_exit.c 91140 2002-02-23 11:12:57Z tanimura $ 40 */ 41 42#include "opt_compat.h" 43#include "opt_ktrace.h" 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/sysproto.h> 48#include <sys/kernel.h> 49#include <sys/malloc.h> 50#include <sys/lock.h> 51#include <sys/mutex.h> 52#include <sys/proc.h> 53#include <sys/pioctl.h> 54#include <sys/tty.h> 55#include <sys/wait.h> 56#include <sys/vnode.h> 57#include <sys/vmmeter.h> 58#include <sys/resourcevar.h> 59#include <sys/signalvar.h> 60#include <sys/sx.h> 61#include <sys/ptrace.h> 62#include <sys/acct.h> /* for acct_process() function prototype */ 63#include <sys/filedesc.h> 64#include <sys/shm.h> 65#include <sys/sem.h> 66#include <sys/jail.h> 67 68#include <vm/vm.h> 69#include <vm/vm_param.h> 70#include <vm/vm_extern.h> 71#include <vm/pmap.h> 72#include <vm/vm_map.h> 73#include <vm/vm_zone.h> 74#include <sys/user.h> 75 76/* Required to be non-static for SysVR4 emulator */ 77MALLOC_DEFINE(M_ZOMBIE, "zombie", "zombie proc status"); 78 79static MALLOC_DEFINE(M_ATEXIT, "atexit", "atexit callback"); 80 81static int wait1 __P((struct thread *, struct wait_args *, int)); 82 83/* 84 * callout list for things to do at exit time 85 */ 86struct exitlist { 87 exitlist_fn function; 88 TAILQ_ENTRY(exitlist) next; 89}; 90 91TAILQ_HEAD(exit_list_head, exitlist); 92static struct exit_list_head exit_list = TAILQ_HEAD_INITIALIZER(exit_list); 93 94/* 95 * exit -- 96 * Death of process. 97 * 98 * MPSAFE 99 */ 100void 101sys_exit(td, uap) 102 struct thread *td; 103 struct sys_exit_args /* { 104 int rval; 105 } */ *uap; 106{ 107 108 mtx_lock(&Giant); 109 exit1(td, W_EXITCODE(uap->rval, 0)); 110 /* NOTREACHED */ 111} 112 113/* 114 * Exit: deallocate address space and other resources, change proc state 115 * to zombie, and unlink proc from allproc and parent's lists. Save exit 116 * status and rusage for wait(). Check for child processes and orphan them. 117 */ 118void 119exit1(td, rv) 120 register struct thread *td; 121 int rv; 122{ 123 struct proc *p = td->td_proc; 124 register struct proc *q, *nq; 125 register struct vmspace *vm; 126 struct vnode *vtmp; 127 struct exitlist *ep; 128 struct vnode *ttyvp; 129 struct tty *tp; 130 131 GIANT_REQUIRED; 132 133 if (p->p_pid == 1) { 134 printf("init died (signal %d, exit %d)\n", 135 WTERMSIG(rv), WEXITSTATUS(rv)); 136 panic("Going nowhere without my init!"); 137 } 138 139/* XXXXKSE */ 140/* MUST abort all other threads before proceeding past this point */ 141 142 /* are we a task leader? */ 143 PROC_LOCK(p); 144 if(p == p->p_leader) { 145 q = p->p_peers; 146 while (q != NULL) { 147 PROC_LOCK(q); 148 psignal(q, SIGKILL); 149 PROC_UNLOCK(q); 150 q = q->p_peers; 151 } 152 while (p->p_peers) 153 msleep((caddr_t)p, &p->p_mtx, PWAIT, "exit1", 0); 154 } 155 PROC_UNLOCK(p); 156 157#ifdef PGINPROF 158 vmsizmon(); 159#endif 160 STOPEVENT(p, S_EXIT, rv); 161 wakeup(&p->p_stype); /* Wakeup anyone in procfs' PIOCWAIT */ 162 163 /* 164 * Check if any loadable modules need anything done at process exit. 165 * e.g. SYSV IPC stuff 166 * XXX what if one of these generates an error? 167 */ 168 TAILQ_FOREACH(ep, &exit_list, next) 169 (*ep->function)(p); 170 171 stopprofclock(p); 172 173 MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), 174 M_ZOMBIE, M_WAITOK); 175 /* 176 * If parent is waiting for us to exit or exec, 177 * P_PPWAIT is set; we will wakeup the parent below. 178 */ 179 PROC_LOCK(p); 180 p->p_flag &= ~(P_TRACED | P_PPWAIT); 181 p->p_flag |= P_WEXIT; 182 SIGEMPTYSET(p->p_siglist); 183 PROC_UNLOCK(p); 184 if (timevalisset(&p->p_realtimer.it_value)) 185 callout_stop(&p->p_itcallout); 186 187 /* 188 * Reset any sigio structures pointing to us as a result of 189 * F_SETOWN with our pid. 190 */ 191 PROC_LOCK(p); 192 funsetownlst(&p->p_sigiolst); 193 PROC_UNLOCK(p); 194 195 /* 196 * Close open files and release open-file table. 197 * This may block! 198 */ 199 fdfree(td); /* XXXKSE *//* may not be the one in proc */ 200 201 /* 202 * Remove ourself from our leader's peer list and wake our leader. 203 */ 204 PROC_LOCK(p->p_leader); 205 if(p->p_leader->p_peers) { 206 q = p->p_leader; 207 while(q->p_peers != p) 208 q = q->p_peers; 209 q->p_peers = p->p_peers; 210 wakeup((caddr_t)p->p_leader); 211 } 212 PROC_UNLOCK(p->p_leader); 213 214 /* The next two chunks should probably be moved to vmspace_exit. */ 215 vm = p->p_vmspace; 216 /* 217 * Release user portion of address space. 218 * This releases references to vnodes, 219 * which could cause I/O if the file has been unlinked. 220 * Need to do this early enough that we can still sleep. 221 * Can't free the entire vmspace as the kernel stack 222 * may be mapped within that space also. 223 */ 224 if (--vm->vm_refcnt == 0) { 225 if (vm->vm_shm) 226 shmexit(p); 227 pmap_remove_pages(vmspace_pmap(vm), VM_MIN_ADDRESS, 228 VM_MAXUSER_ADDRESS); 229 (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, 230 VM_MAXUSER_ADDRESS); 231 vm->vm_freer = p; 232 } 233 234 PGRPSESS_XLOCK(); 235 if (SESS_LEADER(p)) { 236 register struct session *sp; 237 238 sp = p->p_session; 239 if (sp->s_ttyvp) { 240 /* 241 * Controlling process. 242 * Signal foreground pgrp, 243 * drain controlling terminal 244 * and revoke access to controlling terminal. 245 */ 246 if (sp->s_ttyp && (sp->s_ttyp->t_session == sp)) { 247 tp = sp->s_ttyp; 248 if (sp->s_ttyp->t_pgrp) { 249 PGRP_LOCK(sp->s_ttyp->t_pgrp); 250 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 251 PGRP_UNLOCK(sp->s_ttyp->t_pgrp); 252 } 253 /* XXX tp should be locked. */ 254 (void) ttywait(tp); 255 /* 256 * The tty could have been revoked 257 * if we blocked. 258 */ 259 if (sp->s_ttyvp) { 260 ttyvp = sp->s_ttyvp; 261 SESS_LOCK(p->p_session); 262 sp->s_ttyvp = NULL; 263 SESS_UNLOCK(p->p_session); 264 PGRPSESS_XUNLOCK(); 265 VOP_REVOKE(ttyvp, REVOKEALL); 266 PGRPSESS_XLOCK(); 267 vrele(ttyvp); 268 } 269 } 270 if (sp->s_ttyvp) { 271 ttyvp = sp->s_ttyvp; 272 SESS_LOCK(p->p_session); 273 sp->s_ttyvp = NULL; 274 SESS_UNLOCK(p->p_session); 275 vrele(ttyvp); 276 } 277 /* 278 * s_ttyp is not zero'd; we use this to indicate 279 * that the session once had a controlling terminal. 280 * (for logging and informational purposes) 281 */ 282 } 283 SESS_LOCK(p->p_session); 284 sp->s_leader = NULL; 285 SESS_UNLOCK(p->p_session); 286 } 287 fixjobc(p, p->p_pgrp, 0); 288 PGRPSESS_XUNLOCK(); 289 (void)acct_process(td); 290#ifdef KTRACE 291 /* 292 * release trace file 293 */ 294 p->p_traceflag = 0; /* don't trace the vrele() */ 295 if ((vtmp = p->p_tracep) != NULL) { 296 p->p_tracep = NULL; 297 vrele(vtmp); 298 } 299#endif 300 /* 301 * Release reference to text vnode 302 */ 303 if ((vtmp = p->p_textvp) != NULL) { 304 p->p_textvp = NULL; 305 vrele(vtmp); 306 } 307 308 /* 309 * Remove proc from allproc queue and pidhash chain. 310 * Place onto zombproc. Unlink from parent's child list. 311 */ 312 sx_xlock(&allproc_lock); 313 LIST_REMOVE(p, p_list); 314 LIST_INSERT_HEAD(&zombproc, p, p_list); 315 LIST_REMOVE(p, p_hash); 316 sx_xunlock(&allproc_lock); 317 318 sx_xlock(&proctree_lock); 319 q = LIST_FIRST(&p->p_children); 320 if (q != NULL) /* only need this if any child is S_ZOMB */ 321 wakeup((caddr_t) initproc); 322 for (; q != NULL; q = nq) { 323 nq = LIST_NEXT(q, p_sibling); 324 PROC_LOCK(q); 325 proc_reparent(q, initproc); 326 q->p_sigparent = SIGCHLD; 327 /* 328 * Traced processes are killed 329 * since their existence means someone is screwing up. 330 */ 331 if (q->p_flag & P_TRACED) { 332 q->p_flag &= ~P_TRACED; 333 psignal(q, SIGKILL); 334 } 335 PROC_UNLOCK(q); 336 } 337 338 /* 339 * Save exit status and final rusage info, adding in child rusage 340 * info and self times. 341 */ 342 p->p_xstat = rv; 343 *p->p_ru = p->p_stats->p_ru; 344 mtx_lock_spin(&sched_lock); 345 calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL); 346 mtx_unlock_spin(&sched_lock); 347 ruadd(p->p_ru, &p->p_stats->p_cru); 348 349 /* 350 * Pretend that an mi_switch() to the next process occurs now. We 351 * must set `switchtime' directly since we will call cpu_switch() 352 * directly. Set it now so that the rest of the exit time gets 353 * counted somewhere if possible. 354 */ 355 mtx_lock_spin(&sched_lock); 356 binuptime(PCPU_PTR(switchtime)); 357 PCPU_SET(switchticks, ticks); 358 mtx_unlock_spin(&sched_lock); 359 360 /* 361 * notify interested parties of our demise. 362 */ 363 PROC_LOCK(p); 364 PROC_LOCK(p->p_pptr); 365 KNOTE(&p->p_klist, NOTE_EXIT); 366 367 /* 368 * Notify parent that we're gone. If parent has the PS_NOCLDWAIT 369 * flag set, notify process 1 instead (and hope it will handle 370 * this situation). 371 */ 372 if (p->p_pptr->p_procsig->ps_flag & PS_NOCLDWAIT) { 373 struct proc *pp = p->p_pptr; 374 PROC_UNLOCK(pp); 375 proc_reparent(p, initproc); 376 PROC_LOCK(p->p_pptr); 377 /* 378 * If this was the last child of our parent, notify 379 * parent, so in case he was wait(2)ing, he will 380 * continue. 381 */ 382 if (LIST_EMPTY(&pp->p_children)) 383 wakeup((caddr_t)pp); 384 } 385 386 if (p->p_sigparent && p->p_pptr != initproc) 387 psignal(p->p_pptr, p->p_sigparent); 388 else 389 psignal(p->p_pptr, SIGCHLD); 390 PROC_UNLOCK(p->p_pptr); 391 392 /* 393 * If this is a kthread, then wakeup anyone waiting for it to exit. 394 */ 395 if (p->p_flag & P_KTHREAD) 396 wakeup((caddr_t)p); 397 PROC_UNLOCK(p); 398 sx_xunlock(&proctree_lock); 399 400 /* 401 * Clear curproc after we've done all operations 402 * that could block, and before tearing down the rest 403 * of the process state that might be used from clock, etc. 404 * Also, can't clear curproc while we're still runnable, 405 * as we're not on a run queue (we are current, just not 406 * a proper proc any longer!). 407 * 408 * Other substructures are freed from wait(). 409 */ 410 mtx_assert(&Giant, MA_OWNED); 411 if (--p->p_limit->p_refcnt == 0) { 412 FREE(p->p_limit, M_SUBPROC); 413 p->p_limit = NULL; 414 } 415 416 /* 417 * Release this thread's reference to the ucred. The actual proc 418 * reference will stay around until the proc is harvested by 419 * wait(). At this point the ucred is immutable (no other threads 420 * from this proc are around that can change it) so we leave the 421 * per-thread ucred pointer intact in case it is needed although 422 * in theory nothing should be using it at this point. 423 */ 424 crfree(td->td_ucred); 425 426 /* 427 * Finally, call machine-dependent code to release the remaining 428 * resources including address space, the kernel stack and pcb. 429 * The address space is released by "vmspace_exitfree(p)" in 430 * vm_waitproc(). 431 */ 432 cpu_exit(td); 433 434 PROC_LOCK(p); 435 mtx_lock_spin(&sched_lock); 436 while (mtx_owned(&Giant)) 437 mtx_unlock(&Giant); 438 439 /* 440 * We have to wait until after releasing all locks before 441 * changing p_stat. If we block on a mutex then we will be 442 * back at SRUN when we resume and our parent will never 443 * harvest us. 444 */ 445 p->p_stat = SZOMB; 446 447 wakeup(p->p_pptr); 448 PROC_UNLOCK(p); 449 450 cnt.v_swtch++; 451 cpu_throw(); 452 panic("exit1"); 453} 454 455#ifdef COMPAT_43 456/* 457 * MPSAFE, the dirty work is handled by wait1(). 458 */ 459int 460owait(td, uap) 461 struct thread *td; 462 register struct owait_args /* { 463 int dummy; 464 } */ *uap; 465{ 466 struct wait_args w; 467 468 w.options = 0; 469 w.rusage = NULL; 470 w.pid = WAIT_ANY; 471 w.status = NULL; 472 return (wait1(td, &w, 1)); 473} 474#endif /* COMPAT_43 */ 475 476/* 477 * MPSAFE, the dirty work is handled by wait1(). 478 */ 479int 480wait4(td, uap) 481 struct thread *td; 482 struct wait_args *uap; 483{ 484 485 return (wait1(td, uap, 0)); 486} 487 488/* 489 * MPSAFE 490 */ 491static int 492wait1(td, uap, compat) 493 register struct thread *td; 494 register struct wait_args /* { 495 int pid; 496 int *status; 497 int options; 498 struct rusage *rusage; 499 } */ *uap; 500 int compat; 501{ 502 register int nfound; 503 register struct proc *q, *p, *t; 504 int status, error; 505 506 mtx_lock(&Giant); 507 q = td->td_proc; 508 if (uap->pid == 0) { 509 PROC_LOCK(q); 510 uap->pid = -q->p_pgid; 511 PROC_UNLOCK(q); 512 } 513 if (uap->options &~ (WUNTRACED|WNOHANG|WLINUXCLONE)) { 514 error = EINVAL; 515 goto done2; 516 } 517loop: 518 nfound = 0; 519 sx_slock(&proctree_lock); 520 LIST_FOREACH(p, &q->p_children, p_sibling) { 521 PROC_LOCK(p); 522 if (uap->pid != WAIT_ANY && 523 p->p_pid != uap->pid && p->p_pgid != -uap->pid) { 524 PROC_UNLOCK(p); 525 continue; 526 } 527 528 /* 529 * This special case handles a kthread spawned by linux_clone 530 * (see linux_misc.c). The linux_wait4 and linux_waitpid 531 * functions need to be able to distinguish between waiting 532 * on a process and waiting on a thread. It is a thread if 533 * p_sigparent is not SIGCHLD, and the WLINUXCLONE option 534 * signifies we want to wait for threads and not processes. 535 */ 536 if ((p->p_sigparent != SIGCHLD) ^ 537 ((uap->options & WLINUXCLONE) != 0)) { 538 PROC_UNLOCK(p); 539 continue; 540 } 541 542 nfound++; 543 mtx_lock_spin(&sched_lock); 544 if (p->p_stat == SZOMB) { 545 /* 546 * charge childs scheduling cpu usage to parent 547 * XXXKSE assume only one thread & kse & ksegrp 548 * keep estcpu in each ksegrp 549 * so charge it to the ksegrp that did the wait 550 * since process estcpu is sum of all ksegrps, 551 * this is strictly as expected. 552 * Assume that the child process aggregated all 553 * tke estcpu into the 'build-in' ksegrp. 554 * XXXKSE 555 */ 556 if (curthread->td_proc->p_pid != 1) { 557 curthread->td_ksegrp->kg_estcpu = 558 ESTCPULIM(curthread->td_ksegrp->kg_estcpu + 559 p->p_ksegrp.kg_estcpu); 560 } 561 562 mtx_unlock_spin(&sched_lock); 563 PROC_UNLOCK(p); 564 sx_sunlock(&proctree_lock); 565 566 td->td_retval[0] = p->p_pid; 567#ifdef COMPAT_43 568 if (compat) 569 td->td_retval[1] = p->p_xstat; 570 else 571#endif 572 if (uap->status) { 573 status = p->p_xstat; /* convert to int */ 574 if ((error = copyout((caddr_t)&status, 575 (caddr_t)uap->status, sizeof(status)))) { 576 goto done2; 577 } 578 } 579 if (uap->rusage && (error = copyout((caddr_t)p->p_ru, 580 (caddr_t)uap->rusage, sizeof (struct rusage)))) { 581 goto done2; 582 } 583 /* 584 * If we got the child via a ptrace 'attach', 585 * we need to give it back to the old parent. 586 */ 587 sx_xlock(&proctree_lock); 588 if (p->p_oppid) { 589 if ((t = pfind(p->p_oppid)) != NULL) { 590 PROC_LOCK(p); 591 p->p_oppid = 0; 592 proc_reparent(p, t); 593 PROC_UNLOCK(p); 594 psignal(t, SIGCHLD); 595 wakeup((caddr_t)t); 596 PROC_UNLOCK(t); 597 sx_xunlock(&proctree_lock); 598 error = 0; 599 goto done2; 600 } 601 } 602 sx_xunlock(&proctree_lock); 603 PROC_LOCK(p); 604 p->p_xstat = 0; 605 PROC_UNLOCK(p); 606 ruadd(&q->p_stats->p_cru, p->p_ru); 607 FREE(p->p_ru, M_ZOMBIE); 608 p->p_ru = NULL; 609 610 /* 611 * Decrement the count of procs running with this uid. 612 */ 613 (void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0); 614 615 /* 616 * Finally finished with old proc entry. 617 * Unlink it from its process group and free it. 618 */ 619 leavepgrp(p); 620 621 sx_xlock(&allproc_lock); 622 LIST_REMOVE(p, p_list); /* off zombproc */ 623 sx_xunlock(&allproc_lock); 624 625 sx_xlock(&proctree_lock); 626 LIST_REMOVE(p, p_sibling); 627 sx_xunlock(&proctree_lock); 628 629 /* 630 * Free up credentials. 631 */ 632 crfree(p->p_ucred); 633 p->p_ucred = NULL; 634 635 /* 636 * Remove unused arguments 637 */ 638 if (p->p_args && --p->p_args->ar_ref == 0) 639 FREE(p->p_args, M_PARGS); 640 641 if (--p->p_procsig->ps_refcnt == 0) { 642 if (p->p_sigacts != &p->p_uarea->u_sigacts) 643 FREE(p->p_sigacts, M_SUBPROC); 644 FREE(p->p_procsig, M_SUBPROC); 645 p->p_procsig = NULL; 646 } 647 648 /* 649 * Give vm and machine-dependent layer a chance 650 * to free anything that cpu_exit couldn't 651 * release while still running in process context. 652 */ 653 vm_waitproc(p); 654 mtx_destroy(&p->p_mtx); 655 zfree(proc_zone, p); 656 nprocs--; 657 error = 0; 658 goto done2; 659 } 660 if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 && 661 (p->p_flag & P_TRACED || uap->options & WUNTRACED)) { 662 mtx_unlock_spin(&sched_lock); 663 p->p_flag |= P_WAITED; 664 PROC_UNLOCK(p); 665 sx_sunlock(&proctree_lock); 666 td->td_retval[0] = p->p_pid; 667#ifdef COMPAT_43 668 if (compat) { 669 td->td_retval[1] = W_STOPCODE(p->p_xstat); 670 error = 0; 671 } else 672#endif 673 if (uap->status) { 674 status = W_STOPCODE(p->p_xstat); 675 error = copyout((caddr_t)&status, 676 (caddr_t)uap->status, sizeof(status)); 677 } else 678 error = 0; 679 goto done2; 680 } 681 mtx_unlock_spin(&sched_lock); 682 PROC_UNLOCK(p); 683 } 684 sx_sunlock(&proctree_lock); 685 if (nfound == 0) { 686 error = ECHILD; 687 goto done2; 688 } 689 if (uap->options & WNOHANG) { 690 td->td_retval[0] = 0; 691 error = 0; 692 goto done2; 693 } 694 if ((error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) != 0) 695 goto done2; 696 goto loop; 697done2: 698 mtx_unlock(&Giant); 699 return(error); 700} 701 702/* 703 * Make process 'parent' the new parent of process 'child'. 704 * Must be called with an exclusive hold of proctree lock. 705 */ 706void 707proc_reparent(child, parent) 708 register struct proc *child; 709 register struct proc *parent; 710{ 711 712 sx_assert(&proctree_lock, SX_XLOCKED); 713 PROC_LOCK_ASSERT(child, MA_OWNED); 714 if (child->p_pptr == parent) 715 return; 716 717 LIST_REMOVE(child, p_sibling); 718 LIST_INSERT_HEAD(&parent->p_children, child, p_sibling); 719 child->p_pptr = parent; 720} 721 722/* 723 * The next two functions are to handle adding/deleting items on the 724 * exit callout list 725 * 726 * at_exit(): 727 * Take the arguments given and put them onto the exit callout list, 728 * However first make sure that it's not already there. 729 * returns 0 on success. 730 */ 731 732int 733at_exit(function) 734 exitlist_fn function; 735{ 736 struct exitlist *ep; 737 738#ifdef INVARIANTS 739 /* Be noisy if the programmer has lost track of things */ 740 if (rm_at_exit(function)) 741 printf("WARNING: exit callout entry (%p) already present\n", 742 function); 743#endif 744 ep = malloc(sizeof(*ep), M_ATEXIT, M_NOWAIT); 745 if (ep == NULL) 746 return (ENOMEM); 747 ep->function = function; 748 TAILQ_INSERT_TAIL(&exit_list, ep, next); 749 return (0); 750} 751 752/* 753 * Scan the exit callout list for the given item and remove it. 754 * Returns the number of items removed (0 or 1) 755 */ 756int 757rm_at_exit(function) 758 exitlist_fn function; 759{ 760 struct exitlist *ep; 761 762 TAILQ_FOREACH(ep, &exit_list, next) { 763 if (ep->function == function) { 764 TAILQ_REMOVE(&exit_list, ep, next); 765 free(ep, M_ATEXIT); 766 return(1); 767 } 768 } 769 return (0); 770} 771