* Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
* %sccs.include.redist.c%
* @(#)kern_exit.c 7.32 (Berkeley) %G%
* 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.
if (p
->p_vmspace
->vm_shm
)
vmspace_free(p
->p_vmspace
);
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)
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
);
if (--p
->p_cred
->p_refcnt
== 0) {
crfree(p
->p_cred
->pc_ucred
);
FREE(p
->p_cred
, 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
);
u
.u_pcb
.pcb_savacc
.faddr
= (float *)NULL
;
* Free the memory for the user structure and kernel stack.
* As we continue using it until the swtch completes
* (or switches to an interrupt stack), we need to block
* memory allocation by raising priority until we are gone.
/* 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_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
);
* 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
)
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))