* Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)kern_exit.c 7.35 (Berkeley) 6/27/91
* Exit system call: pass back caller's arg
exit(p
, W_EXITCODE(uap
->rval
, 0));
* Exit: deallocate address space and other resources,
* change proc state to zombie, and unlink proc from allproc
* and parent's lists. Save exit status and rusage for wait().
* Check for child processes and orphan them.
register struct proc
*q
, *nq
;
register struct proc
**pp
;
MALLOC(p
->p_ru
, struct rusage
*, sizeof(struct rusage
),
* If parent is waiting for us to exit or exec,
* SPPWAIT is set; we will wakeup the parent below.
p
->p_flag
&= ~(STRC
|SPPWAIT
);
untimeout(realitexpire
, (caddr_t
)p
);
* Close open files and release open-file table.
/* The next two chunks should probably be moved to vmspace_exit. */
if (p
->p_vmspace
->vm_shm
)
* Release user portion of address space.
* This releases references to vnodes,
* which could cause I/O if the file has been unlinked.
* Need to do this early enough that we can still sleep.
* Can't free the entire vmspace as the kernel stack
* may be mapped within that space also.
if (p
->p_vmspace
->vm_refcnt
== 1)
(void) vm_map_remove(&p
->p_vmspace
->vm_map
, VM_MIN_ADDRESS
,
register struct session
*sp
= p
->p_session
;
* Signal foreground pgrp,
* drain controlling terminal
* and revoke access to controlling terminal.
if (sp
->s_ttyp
->t_session
== sp
) {
pgsignal(sp
->s_ttyp
->t_pgrp
, SIGHUP
, 1);
(void) ttywait(sp
->s_ttyp
);
* s_ttyp is not zero'd; we use this to indicate
* that the session once had a controlling terminal.
* (for logging and informational purposes)
fixjobc(p
, p
->p_pgrp
, 0);
p
->p_rlimit
[RLIMIT_FSIZE
].rlim_cur
= RLIM_INFINITY
;
if (--p
->p_limit
->p_refcnt
== 0)
FREE(p
->p_limit
, M_SUBPROC
);
* Remove proc from allproc queue and pidhash chain.
* Place onto zombproc. Unlink from parent's child list.
if (*p
->p_prev
= p
->p_nxt
)
p
->p_nxt
->p_prev
= p
->p_prev
;
p
->p_nxt
->p_prev
= &p
->p_nxt
;
for (pp
= &pidhash
[PIDHASH(p
->p_pid
)]; *pp
; pp
= &(*pp
)->p_hash
)
if (p
->p_cptr
) /* only need this if any child is S_ZOMB */
wakeup((caddr_t
) initproc
);
for (q
= p
->p_cptr
; q
!= NULL
; q
= nq
) {
initproc
->p_cptr
->p_ysptr
= q
;
q
->p_osptr
= initproc
->p_cptr
;
* Traced processes are killed
* since their existence means someone is screwing up.
* Save exit status and final rusage info,
* adding in child rusage info and self times.
*p
->p_ru
= p
->p_stats
->p_ru
;
p
->p_ru
->ru_stime
= p
->p_stime
;
p
->p_ru
->ru_utime
= p
->p_utime
;
ruadd(p
->p_ru
, &p
->p_stats
->p_cru
);
* Notify parent that we're gone.
psignal(p
->p_pptr
, SIGCHLD
);
wakeup((caddr_t
)p
->p_pptr
);
/* move this to cpu_exit */
p
->p_addr
->u_pcb
.pcb_savacc
.faddr
= (float *)NULL
;
* Finally, call machine-dependent code to release the remaining
* resources including address space, the kernel stack and pcb.
* The address space is released by "vmspace_free(p->p_vmspace)";
* This is machine-dependent, as we may have to change stacks
* or ensure that the current one isn't reallocated before we
* finish. cpu_exit will end with a call to swtch(), finishing
* our execution (pun intended).
if ((p
->p_regs
[PS
] & PSL_ALLCC
) != PSL_ALLCC
) {
uap
->options
= p
->p_regs
[R0
];
uap
->rusage
= (struct rusage
*)p
->p_regs
[R1
];
return (wait1(p
, uap
, retval
));
return (wait1(p
, uap
, retval
));
* Wait: check child processes to see if any have exited,
* stopped under trace, or (optionally) stopped by a signal.
* Pass back status and deallocate exited child's proc structure.
if (uap
->options
&~ (WUNTRACED
|WNOHANG
))
for (p
= q
->p_cptr
; p
; p
= p
->p_osptr
) {
if (uap
->pid
!= WAIT_ANY
&&
p
->p_pid
!= uap
->pid
&& p
->p_pgid
!= -uap
->pid
)
if (p
->p_stat
== SZOMB
) {
status
= p
->p_xstat
; /* convert to int */
if (error
= copyout((caddr_t
)&status
,
(caddr_t
)uap
->status
, sizeof(status
)))
if (uap
->rusage
&& (error
= copyout((caddr_t
)p
->p_ru
,
(caddr_t
)uap
->rusage
, sizeof (struct rusage
))))
ruadd(&q
->p_stats
->p_cru
, p
->p_ru
);
if (--p
->p_cred
->p_refcnt
== 0) {
crfree(p
->p_cred
->pc_ucred
);
FREE(p
->p_cred
, M_SUBPROC
);
* Finally finished with old proc entry.
* Unlink it from its process group and free it.
if (*p
->p_prev
= p
->p_nxt
) /* off zombproc */
p
->p_nxt
->p_prev
= p
->p_prev
;
if ((q
= p
->p_pptr
)->p_cptr
== p
)
* Give machine-dependent layer a chance
* to free anything that cpu_exit couldn't
* release while still running in process context.
if (p
->p_stat
== SSTOP
&& (p
->p_flag
& SWTED
) == 0 &&
(p
->p_flag
& STRC
|| uap
->options
& WUNTRACED
)) {
retval
[1] = W_STOPCODE(p
->p_xstat
);
status
= W_STOPCODE(p
->p_xstat
);
error
= copyout((caddr_t
)&status
,
(caddr_t
)uap
->status
, sizeof(status
));
if (uap
->options
& WNOHANG
) {
if (error
= tsleep((caddr_t
)q
, PWAIT
| PCATCH
, "wait", 0))