missing vput
[unix-history] / usr / src / sys / kern / kern_exit.c
CommitLineData
da7c5cc6 1/*
c4ec2128
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
dbf0c423 5 * %sccs.include.redist.c%
c4ec2128 6 *
dbf0c423 7 * @(#)kern_exit.c 7.26 (Berkeley) %G%
da7c5cc6 8 */
a8560fa0 9
94368568
JB
10#include "param.h"
11#include "systm.h"
12#include "map.h"
1bfd8b20
KM
13#include "ioctl.h"
14#include "tty.h"
d9c2f47f 15#include "user.h"
94368568
JB
16#include "kernel.h"
17#include "proc.h"
18#include "buf.h"
19#include "wait.h"
20#include "vm.h"
21#include "file.h"
c4ec2128 22#include "vnode.h"
5e63dd78 23#include "syslog.h"
61d22ffc 24#include "malloc.h"
a8560fa0 25
d301d150 26#include "machine/reg.h"
1ad494e6 27#ifdef COMPAT_43
d301d150 28#include "machine/psl.h"
1ad494e6
MK
29#endif
30
a8560fa0
SL
31/*
32 * Exit system call: pass back caller's arg
33 */
1bfd8b20
KM
34/* ARGSUSED */
35rexit(p, uap, retval)
36 struct proc *p;
37 struct args {
a8560fa0
SL
38 int rval;
39 } *uap;
1bfd8b20
KM
40 int *retval;
41{
a8560fa0 42
d9c2f47f 43 return (exit(p, W_EXITCODE(uap->rval, 0)));
a8560fa0
SL
44}
45
46/*
47 * Release resources.
48 * Save u. area for parent to look at.
49 * Enter zombie state.
50 * Wake up parent and init processes,
51 * and dispose of children.
52 */
1bfd8b20
KM
53exit(p, rv)
54 struct proc *p;
c35e8b3f 55 int rv;
a8560fa0
SL
56{
57 register int i;
1bfd8b20 58 register struct proc *q, *nq;
4a438310 59 register struct proc **pp;
a8560fa0
SL
60
61#ifdef PGINPROF
62 vmsizmon();
63#endif
61d22ffc
KM
64 MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
65 M_ZOMBIE, M_WAITOK);
a8560fa0
SL
66 p->p_flag &= ~(STRC|SULOCK);
67 p->p_flag |= SWEXIT;
dd012d1e 68 p->p_sigignore = ~0;
a2528931 69 p->p_sig = 0;
a8560fa0
SL
70 p->p_cpticks = 0;
71 p->p_pctcpu = 0;
dd012d1e 72 for (i = 0; i < NSIG; i++)
a8560fa0
SL
73 u.u_signal[i] = SIG_IGN;
74 untimeout(realitexpire, (caddr_t)p);
75 /*
76 * Release virtual memory. If we resulted from
77 * a vfork(), instead give the resources back to
78 * the parent.
79 */
bdc59cee
KM
80 if ((p->p_flag & SVFORK) == 0) {
81#ifdef MAPMEM
82 if (u.u_mmap)
1bfd8b20 83 (void) mmexit(p);
bdc59cee 84#endif
a8560fa0 85 vrelvm();
bdc59cee 86 } else {
a8560fa0
SL
87 p->p_flag &= ~SVFORK;
88 wakeup((caddr_t)p);
89 while ((p->p_flag & SVFDONE) == 0)
90 sleep((caddr_t)p, PZERO - 1);
91 p->p_flag &= ~SVFDONE;
92 }
48faa1e9 93 for (i = 0; i <= u.u_lastfile; i++) {
a8560fa0 94 struct file *f;
a8560fa0
SL
95
96 f = u.u_ofile[i];
48faa1e9
MK
97 if (f) {
98 u.u_ofile[i] = NULL;
99 u.u_pofile[i] = 0;
22e4e5b9 100 (void) closef(f);
48faa1e9 101 }
a8560fa0 102 }
1ad494e6 103 if (SESS_LEADER(p)) {
a38b908e
MT
104 register struct session *sp = p->p_session;
105
106 if (sp->s_ttyvp) {
107 /*
108 * Controlling process.
109 * Signal foreground pgrp and revoke access
110 * to controlling terminal.
111 */
112 if (sp->s_ttyp->t_pgrp)
773142c4 113 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
a38b908e
MT
114 vgoneall(sp->s_ttyvp);
115 vrele(sp->s_ttyvp);
116 sp->s_ttyvp = NULL;
61fa8c82
MT
117 /*
118 * s_ttyp is not zero'd; we use this to indicate
119 * that the session once had a controlling terminal.
a38b908e 120 * (for logging and informational purposes)
61fa8c82 121 */
1ad494e6 122 }
a38b908e 123 sp->s_leader = 0;
1ad494e6 124 }
c4ec2128
KM
125 VOP_LOCK(u.u_cdir);
126 vput(u.u_cdir);
a8560fa0 127 if (u.u_rdir) {
c4ec2128
KM
128 VOP_LOCK(u.u_rdir);
129 vput(u.u_rdir);
a8560fa0
SL
130 }
131 u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
d120e510 132 (void) acct(p);
c4ec2128 133 crfree(u.u_cred);
1ad494e6
MK
134#ifdef KTRACE
135 /*
136 * release trace file
137 */
138 if (p->p_tracep)
c4ec2128 139 vrele(p->p_tracep);
a8560fa0 140#endif
db8289b8
MK
141 /*
142 * Freeing the user structure and kernel stack
143 * for the current process: have to run a bit longer
144 * using the pages which are about to be freed...
145 * vrelu will block memory allocation by raising ipl.
146 */
1bfd8b20
KM
147 vrelu(p, 0);
148 vrelpt(p);
1d348849
MK
149 if (*p->p_prev = p->p_nxt) /* off allproc queue */
150 p->p_nxt->p_prev = p->p_prev;
151 if (p->p_nxt = zombproc) /* onto zombproc */
152 p->p_nxt->p_prev = &p->p_nxt;
153 p->p_prev = &zombproc;
154 zombproc = p;
a8560fa0
SL
155 multprog--;
156 p->p_stat = SZOMB;
157 noproc = 1;
4a438310
MK
158 for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
159 if (*pp == p) {
160 *pp = p->p_hash;
161 goto done;
162 }
163 panic("exit");
164done:
48faa1e9
MK
165 if (p->p_pid == 1) {
166 if (p->p_dsize == 0) {
a2528931 167 printf("Can't exec init (errno %d)\n", WEXITSTATUS(rv));
48faa1e9
MK
168 for (;;)
169 ;
170 } else
171 panic("init died");
172 }
a8560fa0 173 p->p_xstat = rv;
48faa1e9 174 *p->p_ru = u.u_ru;
61fa8c82
MT
175 i = splclock();
176 p->p_ru->ru_stime = p->p_stime;
177 p->p_ru->ru_utime = p->p_utime;
178 splx(i);
48faa1e9 179 ruadd(p->p_ru, &u.u_cru);
1d348849
MK
180 if (p->p_cptr) /* only need this if any child is S_ZOMB */
181 wakeup((caddr_t)&proc[1]);
a38b908e 182 fixjobc(p, 0);
1d348849
MK
183 for (q = p->p_cptr; q != NULL; q = nq) {
184 nq = q->p_osptr;
185 if (nq != NULL)
186 nq->p_ysptr = NULL;
187 if (proc[1].p_cptr)
188 proc[1].p_cptr->p_ysptr = q;
189 q->p_osptr = proc[1].p_cptr;
190 q->p_ysptr = NULL;
191 proc[1].p_cptr = q;
a8560fa0 192
1d348849
MK
193 q->p_pptr = &proc[1];
194 q->p_ppid = 1;
195 /*
196 * Traced processes are killed
197 * since their existence means someone is screwing up.
1d348849
MK
198 */
199 if (q->p_flag&STRC) {
200 q->p_flag &= ~STRC;
201 psignal(q, SIGKILL);
a8560fa0 202 }
1d348849 203 }
bdf8c113 204 p->p_cptr = NULL;
a8560fa0
SL
205 psignal(p->p_pptr, SIGCHLD);
206 wakeup((caddr_t)p->p_pptr);
fb1db32c
MK
207#if defined(tahoe)
208 dkeyrelease(p->p_dkey), p->p_dkey = 0;
209 ckeyrelease(p->p_ckey), p->p_ckey = 0;
210 u.u_pcb.pcb_savacc.faddr = (float *)NULL;
211#endif
a8560fa0
SL
212 swtch();
213}
214
1ad494e6 215#ifdef COMPAT_43
1bfd8b20
KM
216owait(p, uap, retval)
217 struct proc *p;
218 register struct args {
1ad494e6 219 int pid;
a2528931 220 int *status;
1ad494e6
MK
221 int options;
222 struct rusage *rusage;
a2528931 223 int compat;
1bfd8b20
KM
224 } *uap;
225 int *retval;
226{
a8560fa0
SL
227
228 if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
c35e8b3f 229 uap->options = 0;
1ad494e6
MK
230 uap->rusage = 0;
231 } else {
c35e8b3f 232 uap->options = u.u_ar0[R0];
1ad494e6 233 uap->rusage = (struct rusage *)u.u_ar0[R1];
a8560fa0 234 }
1ad494e6
MK
235 uap->pid = WAIT_ANY;
236 uap->status = 0;
a2528931 237 uap->compat = 1;
d9c2f47f 238 return (wait1(p, uap, retval));
1ad494e6
MK
239}
240
1bfd8b20
KM
241wait4(p, uap, retval)
242 struct proc *p;
243 struct args {
a2528931
MK
244 int pid;
245 int *status;
246 int options;
247 struct rusage *rusage;
248 int compat;
1bfd8b20
KM
249 } *uap;
250 int *retval;
251{
a2528931
MK
252
253 uap->compat = 0;
d9c2f47f 254 return (wait1(p, uap, retval));
a8560fa0 255}
a2528931
MK
256#else
257#define wait1 wait4
1ad494e6 258#endif
a8560fa0 259
a8560fa0
SL
260/*
261 * Wait system call.
262 * Search for a terminated (zombie) child,
263 * finally lay it to rest, and collect its status.
264 * Look also for stopped (traced) children,
265 * and pass back status from them.
266 */
1bfd8b20
KM
267wait1(q, uap, retval)
268 register struct proc *q;
269 register struct args {
1ad494e6 270 int pid;
a2528931 271 int *status;
1ad494e6
MK
272 int options;
273 struct rusage *rusage;
a2528931
MK
274#ifdef COMPAT_43
275 int compat;
276#endif
1bfd8b20
KM
277 } *uap;
278 int retval[];
279{
280 register int f;
281 register struct proc *p;
a2528931 282 int status, error;
a8560fa0 283
1ad494e6
MK
284 if (uap->pid == 0)
285 uap->pid = -q->p_pgid;
c35e8b3f 286#ifdef notyet
a2528931 287 if (uap->options &~ (WUNTRACED|WNOHANG))
d9c2f47f 288 return (EINVAL);
c35e8b3f 289#endif
1ad494e6 290loop:
c35e8b3f 291 f = 0;
1d348849 292 for (p = q->p_cptr; p; p = p->p_osptr) {
1ad494e6
MK
293 if (uap->pid != WAIT_ANY &&
294 p->p_pid != uap->pid && p->p_pgid != -uap->pid)
295 continue;
a8560fa0
SL
296 f++;
297 if (p->p_stat == SZOMB) {
1bfd8b20 298 retval[0] = p->p_pid;
1ad494e6 299#ifdef COMPAT_43
a2528931 300 if (uap->compat)
1bfd8b20 301 retval[1] = p->p_xstat;
1ad494e6
MK
302 else
303#endif
304 if (uap->status) {
a2528931
MK
305 status = p->p_xstat; /* convert to int */
306 if (error = copyout((caddr_t)&status,
1ad494e6 307 (caddr_t)uap->status, sizeof(status)))
d9c2f47f 308 return (error);
5e63dd78 309 }
a2528931
MK
310 if (uap->rusage && (error = copyout((caddr_t)p->p_ru,
311 (caddr_t)uap->rusage, sizeof (struct rusage))))
d9c2f47f 312 return (error);
a2528931 313 pgrm(p); /* off pgrp */
1ad494e6 314 p->p_xstat = 0;
1ad494e6
MK
315 ruadd(&u.u_cru, p->p_ru);
316 FREE(p->p_ru, M_ZOMBIE);
317 p->p_ru = 0;
a8560fa0
SL
318 p->p_stat = NULL;
319 p->p_pid = 0;
320 p->p_ppid = 0;
1d348849
MK
321 if (*p->p_prev = p->p_nxt) /* off zombproc */
322 p->p_nxt->p_prev = p->p_prev;
323 p->p_nxt = freeproc; /* onto freeproc */
324 freeproc = p;
a8560fa0
SL
325 if (q = p->p_ysptr)
326 q->p_osptr = p->p_osptr;
327 if (q = p->p_osptr)
328 q->p_ysptr = p->p_ysptr;
329 if ((q = p->p_pptr)->p_cptr == p)
330 q->p_cptr = p->p_osptr;
331 p->p_pptr = 0;
332 p->p_ysptr = 0;
333 p->p_osptr = 0;
334 p->p_cptr = 0;
335 p->p_sig = 0;
dd012d1e
SL
336 p->p_sigcatch = 0;
337 p->p_sigignore = 0;
338 p->p_sigmask = 0;
1ad494e6 339 /*p->p_pgrp = 0;*/
a8560fa0
SL
340 p->p_flag = 0;
341 p->p_wchan = 0;
d9c2f47f 342 return (0);
a8560fa0 343 }
1ad494e6
MK
344 if (p->p_stat == SSTOP && (p->p_flag & SWTED) == 0 &&
345 (p->p_flag & STRC || uap->options & WUNTRACED)) {
a8560fa0 346 p->p_flag |= SWTED;
1bfd8b20 347 retval[0] = p->p_pid;
1ad494e6 348#ifdef COMPAT_43
85d629e3 349 if (uap->compat) {
19dec745 350 retval[1] = W_STOPCODE(p->p_xstat);
85d629e3
KM
351 error = 0;
352 } else
1ad494e6
MK
353#endif
354 if (uap->status) {
19dec745 355 status = W_STOPCODE(p->p_xstat);
a2528931 356 error = copyout((caddr_t)&status,
1ad494e6 357 (caddr_t)uap->status, sizeof(status));
a2528931
MK
358 } else
359 error = 0;
d9c2f47f 360 return (error);
a8560fa0
SL
361 }
362 }
a2528931 363 if (f == 0)
d9c2f47f 364 return (ECHILD);
1ad494e6 365 if (uap->options & WNOHANG) {
1bfd8b20 366 retval[0] = 0;
d9c2f47f 367 return (0);
a8560fa0 368 }
1bfd8b20 369 if (error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))
d9c2f47f 370 return (error);
a8560fa0
SL
371 goto loop;
372}