* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* %sccs.include.redist.c%
* @(#)kern_exit.c 7.29 (Berkeley) %G%
#include "../vm/vm_param.h"
#include "../vm/vm_map.h"
#include "../vm/vm_kern.h"
* Exit system call: pass back caller's arg
exit(p
, W_EXITCODE(uap
->rval
, 0));
* Save u. area for parent to look at.
* Wake up parent and init processes,
* and dispose of children.
register struct proc
*q
, *nq
;
register struct proc
**pp
;
MALLOC(p
->p_ru
, struct rusage
*, sizeof(struct rusage
),
p
->p_flag
&= ~(STRC
|SULOCK
);
for (i
= 0; i
< NSIG
; i
++)
untimeout(realitexpire
, (caddr_t
)p
);
vm_map_deallocate(p
->p_map
);
* XXX preserve synchronization semantics of vfork
if (p
->p_flag
& SVFORK
) {
while ((p
->p_flag
& SVFDONE
) == 0)
sleep((caddr_t
)p
, PZERO
- 1);
for (i
= 0; i
<= u
.u_lastfile
; i
++) {
register struct session
*sp
= p
->p_session
;
* Signal foreground pgrp and revoke access
* to controlling terminal.
pgsignal(sp
->s_ttyp
->t_pgrp
, SIGHUP
, 1);
* s_ttyp is not zero'd; we use this to indicate
* that the session once had a controlling terminal.
* (for logging and informational purposes)
u
.u_rlimit
[RLIMIT_FSIZE
].rlim_cur
= RLIM_INFINITY
;
/* I don't think this will cause a sleep/realloc anywhere... */
kmem_free(kernel_map
, (vm_offset_t
)p
->p_addr
,
round_page(ctob(UPAGES
)));
if (*p
->p_prev
= p
->p_nxt
) /* off allproc queue */
p
->p_nxt
->p_prev
= p
->p_prev
;
if (p
->p_nxt
= zombproc
) /* onto zombproc */
p
->p_nxt
->p_prev
= &p
->p_nxt
;
for (pp
= &pidhash
[PIDHASH(p
->p_pid
)]; *pp
; pp
= &(*pp
)->p_hash
)
p
->p_ru
->ru_stime
= p
->p_stime
;
p
->p_ru
->ru_utime
= p
->p_utime
;
ruadd(p
->p_ru
, &u
.u_cru
);
if (p
->p_cptr
) /* only need this if any child is S_ZOMB */
wakeup((caddr_t
)&proc
[1]);
fixjobc(p
, p
->p_pgrp
, 0);
for (q
= p
->p_cptr
; q
!= NULL
; q
= nq
) {
proc
[1].p_cptr
->p_ysptr
= q
;
q
->p_osptr
= proc
[1].p_cptr
;
* Traced processes are killed
* since their existence means someone is screwing up.
psignal(p
->p_pptr
, SIGCHLD
);
wakeup((caddr_t
)p
->p_pptr
);
dkeyrelease(p
->p_dkey
), p
->p_dkey
= 0;
ckeyrelease(p
->p_ckey
), p
->p_ckey
= 0;
u
.u_pcb
.pcb_savacc
.faddr
= (float *)NULL
;
if ((u
.u_ar0
[PS
] & PSL_ALLCC
) != PSL_ALLCC
) {
uap
->options
= u
.u_ar0
[R0
];
uap
->rusage
= (struct rusage
*)u
.u_ar0
[R1
];
return (wait1(p
, uap
, retval
));
return (wait1(p
, uap
, retval
));
* Search for a terminated (zombie) child,
* finally lay it to rest, and collect its status.
* Look also for stopped (traced) children,
* and pass back status from them.
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(&u
.u_cru
, p
->p_ru
);
if (*p
->p_prev
= p
->p_nxt
) /* off zombproc */
p
->p_nxt
->p_prev
= p
->p_prev
;
p
->p_nxt
= freeproc
; /* onto freeproc */
if ((q
= p
->p_pptr
)->p_cptr
== p
)
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))