1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)kern_exit.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #include "../machine/reg.h"
10: #include "../machine/psl.h"
11:
12: #include "param.h"
13: #include "systm.h"
14: #include "map.h"
15: #include "dir.h"
16: #include "user.h"
17: #include "kernel.h"
18: #include "proc.h"
19: #include "buf.h"
20: #include "wait.h"
21: #include "vm.h"
22: #include "file.h"
23: #include "mbuf.h"
24: #include "inode.h"
25: #include "syslog.h"
26:
27: /*
28: * Exit system call: pass back caller's arg
29: */
30: rexit()
31: {
32: register struct a {
33: int rval;
34: } *uap;
35:
36: uap = (struct a *)u.u_ap;
37: exit((uap->rval & 0377) << 8);
38: }
39:
40: /*
41: * Release resources.
42: * Save u. area for parent to look at.
43: * Enter zombie state.
44: * Wake up parent and init processes,
45: * and dispose of children.
46: */
47: exit(rv)
48: int rv;
49: {
50: register int i;
51: register struct proc *p, *q, *nq;
52: register int x;
53: struct mbuf *m = m_getclr(M_WAIT, MT_ZOMBIE);
54:
55: #ifdef PGINPROF
56: vmsizmon();
57: #endif
58: p = u.u_procp;
59: p->p_flag &= ~(STRC|SULOCK);
60: p->p_flag |= SWEXIT;
61: p->p_sigignore = ~0;
62: p->p_cpticks = 0;
63: p->p_pctcpu = 0;
64: for (i = 0; i < NSIG; i++)
65: u.u_signal[i] = SIG_IGN;
66: untimeout(realitexpire, (caddr_t)p);
67: /*
68: * Release virtual memory. If we resulted from
69: * a vfork(), instead give the resources back to
70: * the parent.
71: */
72: if ((p->p_flag & SVFORK) == 0)
73: vrelvm();
74: else {
75: p->p_flag &= ~SVFORK;
76: wakeup((caddr_t)p);
77: while ((p->p_flag & SVFDONE) == 0)
78: sleep((caddr_t)p, PZERO - 1);
79: p->p_flag &= ~SVFDONE;
80: }
81: for (i = 0; i <= u.u_lastfile; i++) {
82: struct file *f;
83:
84: f = u.u_ofile[i];
85: if (f) {
86: u.u_ofile[i] = NULL;
87: u.u_pofile[i] = 0;
88: closef(f);
89: }
90: }
91: ilock(u.u_cdir);
92: iput(u.u_cdir);
93: if (u.u_rdir) {
94: ilock(u.u_rdir);
95: iput(u.u_rdir);
96: }
97: u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
98: acct();
99: #ifdef QUOTA
100: qclean();
101: #endif
102: /*
103: * Freeing the user structure and kernel stack
104: * for the current process: have to run a bit longer
105: * using the pages which are about to be freed...
106: * vrelu will block memory allocation by raising ipl.
107: */
108: vrelu(u.u_procp, 0);
109: vrelpt(u.u_procp);
110: if (*p->p_prev = p->p_nxt) /* off allproc queue */
111: p->p_nxt->p_prev = p->p_prev;
112: if (p->p_nxt = zombproc) /* onto zombproc */
113: p->p_nxt->p_prev = &p->p_nxt;
114: p->p_prev = &zombproc;
115: zombproc = p;
116: multprog--;
117: p->p_stat = SZOMB;
118: noproc = 1;
119: i = PIDHASH(p->p_pid);
120: x = p - proc;
121: if (pidhash[i] == x)
122: pidhash[i] = p->p_idhash;
123: else {
124: for (i = pidhash[i]; i != 0; i = proc[i].p_idhash)
125: if (proc[i].p_idhash == x) {
126: proc[i].p_idhash = p->p_idhash;
127: goto done;
128: }
129: panic("exit");
130: }
131: if (p->p_pid == 1) {
132: if (p->p_dsize == 0) {
133: printf("Can't exec /etc/init\n");
134: for (;;)
135: ;
136: } else
137: panic("init died");
138: }
139: done:
140: p->p_xstat = rv;
141: p->p_ru = mtod(m, struct rusage *);
142: *p->p_ru = u.u_ru;
143: ruadd(p->p_ru, &u.u_cru);
144: if (p->p_cptr) /* only need this if any child is S_ZOMB */
145: wakeup((caddr_t)&proc[1]);
146: for (q = p->p_cptr; q != NULL; q = nq) {
147: nq = q->p_osptr;
148: if (nq != NULL)
149: nq->p_ysptr = NULL;
150: if (proc[1].p_cptr)
151: proc[1].p_cptr->p_ysptr = q;
152: q->p_osptr = proc[1].p_cptr;
153: q->p_ysptr = NULL;
154: proc[1].p_cptr = q;
155:
156: q->p_pptr = &proc[1];
157: q->p_ppid = 1;
158: /*
159: * Traced processes are killed
160: * since their existence means someone is screwing up.
161: * Stopped processes are sent a hangup and a continue.
162: * This is designed to be ``safe'' for setuid
163: * processes since they must be willing to tolerate
164: * hangups anyways.
165: */
166: if (q->p_flag&STRC) {
167: q->p_flag &= ~STRC;
168: psignal(q, SIGKILL);
169: } else if (q->p_stat == SSTOP) {
170: psignal(q, SIGHUP);
171: psignal(q, SIGCONT);
172: }
173: /*
174: * Protect this process from future
175: * tty signals, clear TSTP/TTIN/TTOU if pending.
176: */
177: (void) spgrp(q);
178: }
179: p->p_cptr = NULL;
180: psignal(p->p_pptr, SIGCHLD);
181: wakeup((caddr_t)p->p_pptr);
182: swtch();
183: }
184:
185: wait()
186: {
187: struct rusage ru, *rup;
188:
189: if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
190: u.u_error = wait1(0, (struct rusage *)0);
191: return;
192: }
193: rup = (struct rusage *)u.u_ar0[R1];
194: u.u_error = wait1(u.u_ar0[R0], &ru);
195: if (u.u_error)
196: return;
197: if (rup != (struct rusage *)0)
198: u.u_error = copyout((caddr_t)&ru, (caddr_t)rup,
199: sizeof (struct rusage));
200: }
201:
202: /*
203: * Wait system call.
204: * Search for a terminated (zombie) child,
205: * finally lay it to rest, and collect its status.
206: * Look also for stopped (traced) children,
207: * and pass back status from them.
208: */
209: wait1(options, ru)
210: register int options;
211: struct rusage *ru;
212: {
213: register f;
214: register struct proc *p, *q;
215:
216: f = 0;
217: loop:
218: q = u.u_procp;
219: for (p = q->p_cptr; p; p = p->p_osptr) {
220: f++;
221: if (p->p_stat == SZOMB) {
222: u.u_r.r_val1 = p->p_pid;
223: u.u_r.r_val2 = p->p_xstat;
224: p->p_xstat = 0;
225: if (ru && p->p_ru)
226: *ru = *p->p_ru;
227: if (p->p_ru) {
228: ruadd(&u.u_cru, p->p_ru);
229: (void) m_free(dtom(p->p_ru));
230: p->p_ru = 0;
231: }
232: p->p_stat = NULL;
233: p->p_pid = 0;
234: p->p_ppid = 0;
235: if (*p->p_prev = p->p_nxt) /* off zombproc */
236: p->p_nxt->p_prev = p->p_prev;
237: p->p_nxt = freeproc; /* onto freeproc */
238: freeproc = p;
239: if (q = p->p_ysptr)
240: q->p_osptr = p->p_osptr;
241: if (q = p->p_osptr)
242: q->p_ysptr = p->p_ysptr;
243: if ((q = p->p_pptr)->p_cptr == p)
244: q->p_cptr = p->p_osptr;
245: p->p_pptr = 0;
246: p->p_ysptr = 0;
247: p->p_osptr = 0;
248: p->p_cptr = 0;
249: p->p_sig = 0;
250: p->p_sigcatch = 0;
251: p->p_sigignore = 0;
252: p->p_sigmask = 0;
253: p->p_pgrp = 0;
254: p->p_flag = 0;
255: p->p_wchan = 0;
256: p->p_cursig = 0;
257: return (0);
258: }
259: if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 &&
260: (p->p_flag&STRC || options&WUNTRACED)) {
261: p->p_flag |= SWTED;
262: u.u_r.r_val1 = p->p_pid;
263: u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED;
264: return (0);
265: }
266: }
267: if (f == 0)
268: return (ECHILD);
269: if (options&WNOHANG) {
270: u.u_r.r_val1 = 0;
271: return (0);
272: }
273: if (setjmp(&u.u_qsave)) {
274: p = u.u_procp;
275: if ((u.u_sigintr & sigmask(p->p_cursig)) != 0)
276: return(EINTR);
277: u.u_eosys = RESTARTSYS;
278: return (0);
279: }
280: sleep((caddr_t)u.u_procp, PWAIT);
281: goto loop;
282: }
Defined functions
exit
defined in line
47; used 1 times
rexit
defined in line
30; used 2 times
wait
defined in line
185; used 3 times
Defined struct's
a
defined in line
32; used 2 times