Made a call which was to sleep() use tsleep() instead.
[unix-history] / sys / kern / kern_exit.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
600f7f07 33 * from: @(#)kern_exit.c 7.35 (Berkeley) 6/27/91
41aefbec 34 * $Id: kern_exit.c,v 1.14 1994/01/29 04:04:23 davidg Exp $
15637ed4
RG
35 */
36
37#include "param.h"
38#include "systm.h"
39#include "ioctl.h"
40#include "tty.h"
41#include "time.h"
42#include "resource.h"
43#include "kernel.h"
44#include "proc.h"
45#include "buf.h"
46#include "wait.h"
47#include "file.h"
48#include "vnode.h"
49#include "syslog.h"
50#include "malloc.h"
fde1aeb2 51#include "signalvar.h"
15637ed4
RG
52#include "resourcevar.h"
53
54#include "machine/cpu.h"
55#ifdef COMPAT_43
56#include "machine/reg.h"
57#include "machine/psl.h"
58#endif
59
60#include "vm/vm.h"
61#include "vm/vm_kern.h"
62
63/*
64 * Exit system call: pass back caller's arg
65 */
3c7eb27c
DG
66
67struct rexit_args {
68 int rval;
69};
15637ed4 70/* ARGSUSED */
603809a1 71void
15637ed4
RG
72rexit(p, uap, retval)
73 struct proc *p;
3c7eb27c 74 struct rexit_args *uap;
15637ed4
RG
75 int *retval;
76{
77
e5b1af89 78 kexit(p, W_EXITCODE(uap->rval, 0));
15637ed4
RG
79 /* NOTREACHED */
80}
81
82/*
83 * Exit: deallocate address space and other resources,
84 * change proc state to zombie, and unlink proc from allproc
85 * and parent's lists. Save exit status and rusage for wait().
86 * Check for child processes and orphan them.
87 */
603809a1 88void
e5b1af89 89kexit(p, rv)
15637ed4
RG
90 register struct proc *p;
91 int rv;
92{
93 register struct proc *q, *nq;
94 register struct proc **pp;
95 int s;
96
749a84ff 97 acct(p); /* MT - do process accounting -- must be done before
603809a1
NW
98 address space is released */
99
15637ed4
RG
100#ifdef PGINPROF
101 vmsizmon();
102#endif
103 MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
104 M_ZOMBIE, M_WAITOK);
105 /*
106 * If parent is waiting for us to exit or exec,
107 * SPPWAIT is set; we will wakeup the parent below.
108 */
109 p->p_flag &= ~(STRC|SPPWAIT);
110 p->p_flag |= SWEXIT;
111 p->p_sigignore = ~0;
112 p->p_sig = 0;
113 untimeout(realitexpire, (caddr_t)p);
114
115 /*
116 * Close open files and release open-file table.
117 * This may block!
118 */
119 fdfree(p);
120
24fd64ab
DG
121#ifdef SYSVSEM
122 semexit(p);
123#endif
124
15637ed4
RG
125 /* The next two chunks should probably be moved to vmspace_exit. */
126#ifdef SYSVSHM
127 if (p->p_vmspace->vm_shm)
128 shmexit(p);
129#endif
130 /*
131 * Release user portion of address space.
132 * This releases references to vnodes,
133 * which could cause I/O if the file has been unlinked.
134 * Need to do this early enough that we can still sleep.
135 * Can't free the entire vmspace as the kernel stack
136 * may be mapped within that space also.
137 */
138 if (p->p_vmspace->vm_refcnt == 1)
139 (void) vm_map_remove(&p->p_vmspace->vm_map, VM_MIN_ADDRESS,
140 VM_MAXUSER_ADDRESS);
141
142 if (p->p_pid == 1)
143 panic("init died");
144
145 if (SESS_LEADER(p)) {
146 register struct session *sp = p->p_session;
147
148 if (sp->s_ttyvp) {
149 /*
150 * Controlling process.
151 * Signal foreground pgrp,
152 * drain controlling terminal
153 * and revoke access to controlling terminal.
154 */
155 if (sp->s_ttyp->t_session == sp) {
156 if (sp->s_ttyp->t_pgrp)
157 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
158 (void) ttywait(sp->s_ttyp);
159 vgoneall(sp->s_ttyvp);
160 }
1396a309 161 vn_close(sp->s_ttyvp, FREAD, p->p_ucred, p);
15637ed4
RG
162 sp->s_ttyvp = NULL;
163 /*
164 * s_ttyp is not zero'd; we use this to indicate
165 * that the session once had a controlling terminal.
166 * (for logging and informational purposes)
167 */
168 }
169 sp->s_leader = NULL;
170 }
171 fixjobc(p, p->p_pgrp, 0);
172 p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
173#ifdef KTRACE
174 /*
175 * release trace file
176 */
177 if (p->p_tracep)
9eafb1ca 178 vn_close(p->p_tracep, FREAD|FWRITE, p->p_ucred, p);
15637ed4
RG
179#endif
180
15637ed4
RG
181 /*
182 * Remove proc from allproc queue and pidhash chain.
183 * Place onto zombproc. Unlink from parent's child list.
184 */
185 if (*p->p_prev = p->p_nxt)
186 p->p_nxt->p_prev = p->p_prev;
187 if (p->p_nxt = zombproc)
188 p->p_nxt->p_prev = &p->p_nxt;
189 p->p_prev = &zombproc;
190 zombproc = p;
191 p->p_stat = SZOMB;
192 for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
193 if (*pp == p) {
194 *pp = p->p_hash;
195 goto done;
196 }
197 panic("exit");
198done:
199
200 if (p->p_cptr) /* only need this if any child is S_ZOMB */
201 wakeup((caddr_t) initproc);
202 for (q = p->p_cptr; q != NULL; q = nq) {
203 nq = q->p_osptr;
204 if (nq != NULL)
205 nq->p_ysptr = NULL;
206 if (initproc->p_cptr)
207 initproc->p_cptr->p_ysptr = q;
208 q->p_osptr = initproc->p_cptr;
209 q->p_ysptr = NULL;
210 initproc->p_cptr = q;
211
212 q->p_pptr = initproc;
213 /*
214 * Traced processes are killed
215 * since their existence means someone is screwing up.
216 */
217 if (q->p_flag&STRC) {
218 q->p_flag &= ~STRC;
219 psignal(q, SIGKILL);
220 }
221 }
222 p->p_cptr = NULL;
223
224 /*
225 * Save exit status and final rusage info,
226 * adding in child rusage info and self times.
227 */
228 p->p_xstat = rv;
229 *p->p_ru = p->p_stats->p_ru;
230 p->p_ru->ru_stime = p->p_stime;
231 p->p_ru->ru_utime = p->p_utime;
232 ruadd(p->p_ru, &p->p_stats->p_cru);
233
234 /*
235 * Notify parent that we're gone.
236 */
237 psignal(p->p_pptr, SIGCHLD);
238 wakeup((caddr_t)p->p_pptr);
239#if defined(tahoe)
240 /* move this to cpu_exit */
241 p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
242#endif
1396a309
DG
243 /*
244 * current process does not exist, as far as other parts of the
245 * system (clock) is concerned, since parts of it might not be
246 * there anymore
247 */
248 curproc = NULL;
249
250 if (--p->p_limit->p_refcnt == 0) {
251 FREE(p->p_limit, M_SUBPROC);
252 p->p_limit = (struct plimit *) -1;
253 }
254
15637ed4
RG
255 /*
256 * Finally, call machine-dependent code to release the remaining
257 * resources including address space, the kernel stack and pcb.
258 * The address space is released by "vmspace_free(p->p_vmspace)";
259 * This is machine-dependent, as we may have to change stacks
260 * or ensure that the current one isn't reallocated before we
261 * finish. cpu_exit will end with a call to swtch(), finishing
262 * our execution (pun intended).
263 */
264 cpu_exit(p);
265 /* NOTREACHED */
266}
267
fde1aeb2
GW
268/*
269 * Wait: check child processes to see if any have exited,
270 * stopped under trace, or (optionally) stopped by a signal.
271 * Pass back status and deallocate exited child's proc structure.
272 */
273
274struct wait1_args {
275 int pid;
276 int *status;
277 int options;
278 struct rusage *rusage;
279#ifdef COMPAT_43
280 int compat;
281#endif
282};
283
15637ed4 284#ifdef COMPAT_43
fde1aeb2 285static int wait1(struct proc *, struct wait1_args *, int *);
3c7eb27c
DG
286
287struct owait_args {
288 int pid;
289 int *status;
290 int options;
291 struct rusage *rusage;
292 int compat;
293};
294
4c45483e 295int
15637ed4
RG
296owait(p, uap, retval)
297 struct proc *p;
3c7eb27c 298 register struct owait_args *uap;
15637ed4
RG
299 int *retval;
300{
301
302 uap->options = 0;
303 uap->rusage = 0;
304 uap->pid = WAIT_ANY;
305 uap->status = 0;
306 uap->compat = 1;
fde1aeb2 307 return (wait1(p, (struct wait1_args *)uap, retval));
15637ed4
RG
308}
309
3c7eb27c
DG
310struct wait4_args {
311 int pid;
312 int *status;
313 int options;
314 struct rusage *rusage;
315 int compat;
316};
317
4c45483e 318int
15637ed4
RG
319wait4(p, uap, retval)
320 struct proc *p;
3c7eb27c 321 struct wait4_args *uap;
15637ed4
RG
322 int *retval;
323{
324
325 uap->compat = 0;
fde1aeb2 326 return (wait1(p, (struct wait1_args *)uap, retval));
15637ed4
RG
327}
328#else
329#define wait1 wait4
330#endif
331
fde1aeb2 332static int
3c7eb27c
DG
333wait1(q, uap, retval)
334 register struct proc *q;
335 register struct wait1_args *uap;
15637ed4
RG
336 int retval[];
337{
338 register int nfound;
339 register struct proc *p;
340 int status, error;
341
342 if (uap->pid == 0)
343 uap->pid = -q->p_pgid;
344#ifdef notyet
345 if (uap->options &~ (WUNTRACED|WNOHANG))
346 return (EINVAL);
347#endif
348loop:
349 nfound = 0;
350 for (p = q->p_cptr; p; p = p->p_osptr) {
351 if (uap->pid != WAIT_ANY &&
352 p->p_pid != uap->pid && p->p_pgid != -uap->pid)
353 continue;
354 nfound++;
355 if (p->p_stat == SZOMB) {
41aefbec
DG
356 /* charge childs cpu usage to parent */
357 if( curproc->p_pid != 1)
358 curproc->p_cpu += p->p_cpu;
15637ed4
RG
359 retval[0] = p->p_pid;
360#ifdef COMPAT_43
361 if (uap->compat)
362 retval[1] = p->p_xstat;
363 else
364#endif
365 if (uap->status) {
366 status = p->p_xstat; /* convert to int */
367 if (error = copyout((caddr_t)&status,
368 (caddr_t)uap->status, sizeof(status)))
369 return (error);
370 }
371 if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
372 (caddr_t)uap->rusage, sizeof (struct rusage))))
373 return (error);
374 p->p_xstat = 0;
375 ruadd(&q->p_stats->p_cru, p->p_ru);
376 FREE(p->p_ru, M_ZOMBIE);
377 if (--p->p_cred->p_refcnt == 0) {
378 crfree(p->p_cred->pc_ucred);
379 FREE(p->p_cred, M_SUBPROC);
380 p->p_cred = (struct pcred *) -1;
381 }
382
383 /*
384 * Finally finished with old proc entry.
385 * Unlink it from its process group and free it.
386 */
387 leavepgrp(p);
388 if (*p->p_prev = p->p_nxt) /* off zombproc */
389 p->p_nxt->p_prev = p->p_prev;
390 if (q = p->p_ysptr)
391 q->p_osptr = p->p_osptr;
392 if (q = p->p_osptr)
393 q->p_ysptr = p->p_ysptr;
394 if ((q = p->p_pptr)->p_cptr == p)
395 q->p_cptr = p->p_osptr;
396
397 /*
398 * Give machine-dependent layer a chance
399 * to free anything that cpu_exit couldn't
400 * release while still running in process context.
401 */
402 cpu_wait(p);
403 FREE(p, M_PROC);
404 nprocs--;
405 return (0);
406 }
407 if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
408 (p->p_flag & STRC || uap->options & WUNTRACED)) {
409 p->p_flag |= SWTED;
410 retval[0] = p->p_pid;
411#ifdef COMPAT_43
412 if (uap->compat) {
413 retval[1] = W_STOPCODE(p->p_xstat);
414 error = 0;
415 } else
416#endif
417 if (uap->status) {
418 status = W_STOPCODE(p->p_xstat);
419 error = copyout((caddr_t)&status,
420 (caddr_t)uap->status, sizeof(status));
421 } else
422 error = 0;
423 return (error);
424 }
425 }
426 if (nfound == 0)
427 return (ECHILD);
428 if (uap->options & WNOHANG) {
429 retval[0] = 0;
430 return (0);
431 }
432 if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))
433 return (error);
434 goto loop;
435}