purge #if sun's
[unix-history] / usr / src / sys / kern / kern_exit.c
CommitLineData
e3d5bfde 1/* kern_exit.c 4.6 83/07/01 */
a8560fa0
SL
2
3#include "../machine/reg.h"
4#include "../machine/psl.h"
5
6#include "../h/param.h"
7#include "../h/systm.h"
8#include "../h/map.h"
9#include "../h/dir.h"
10#include "../h/user.h"
11#include "../h/kernel.h"
12#include "../h/proc.h"
13#include "../h/buf.h"
14#include "../h/wait.h"
15#include "../h/vm.h"
16#include "../h/file.h"
17#include "../h/mbuf.h"
18#include "../h/inode.h"
19
20/*
21 * Exit system call: pass back caller's arg
22 */
23rexit()
24{
25 register struct a {
26 int rval;
27 } *uap;
28
29 uap = (struct a *)u.u_ap;
30 exit((uap->rval & 0377) << 8);
31}
32
33/*
34 * Release resources.
35 * Save u. area for parent to look at.
36 * Enter zombie state.
37 * Wake up parent and init processes,
38 * and dispose of children.
39 */
40exit(rv)
41 int rv;
42{
43 register int i;
44 register struct proc *p, *q;
45 register int x;
46 struct mbuf *m = m_getclr(M_WAIT, MT_ZOMBIE);
47
48#ifdef PGINPROF
49 vmsizmon();
50#endif
51 p = u.u_procp;
52 p->p_flag &= ~(STRC|SULOCK);
53 p->p_flag |= SWEXIT;
dd012d1e 54 p->p_sigignore = ~0;
a8560fa0
SL
55 p->p_cpticks = 0;
56 p->p_pctcpu = 0;
dd012d1e 57 for (i = 0; i < NSIG; i++)
a8560fa0
SL
58 u.u_signal[i] = SIG_IGN;
59 untimeout(realitexpire, (caddr_t)p);
60 /*
61 * Release virtual memory. If we resulted from
62 * a vfork(), instead give the resources back to
63 * the parent.
64 */
65 if ((p->p_flag & SVFORK) == 0)
66 vrelvm();
67 else {
68 p->p_flag &= ~SVFORK;
69 wakeup((caddr_t)p);
70 while ((p->p_flag & SVFDONE) == 0)
71 sleep((caddr_t)p, PZERO - 1);
72 p->p_flag &= ~SVFDONE;
73 }
74 for (i = 0; i < NOFILE; i++) {
75 struct file *f;
a8560fa0
SL
76
77 f = u.u_ofile[i];
78 u.u_ofile[i] = NULL;
a8560fa0 79 u.u_pofile[i] = 0;
55dfda24 80 closef(f);
a8560fa0
SL
81 }
82 ilock(u.u_cdir);
83 iput(u.u_cdir);
84 if (u.u_rdir) {
85 ilock(u.u_rdir);
86 iput(u.u_rdir);
87 }
88 u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
89 acct();
90#ifdef QUOTA
91 qclean();
a8560fa0
SL
92#endif
93 vrelpt(u.u_procp);
94 vrelu(u.u_procp, 0);
95 (void) spl5(); /* hack for mem alloc race XXX */
96 multprog--;
97 p->p_stat = SZOMB;
98 noproc = 1;
99 i = PIDHASH(p->p_pid);
100 x = p - proc;
101 if (pidhash[i] == x)
102 pidhash[i] = p->p_idhash;
103 else {
104 for (i = pidhash[i]; i != 0; i = proc[i].p_idhash)
105 if (proc[i].p_idhash == x) {
106 proc[i].p_idhash = p->p_idhash;
107 goto done;
108 }
109 panic("exit");
110 }
111 if (p->p_pid == 1)
112 panic("init died");
113done:
114 p->p_xstat = rv;
115if (m == 0)
116panic("exit: m_getclr");
117 p->p_ru = mtod(m, struct rusage *);
118 *p->p_ru = u.u_ru;
119 ruadd(p->p_ru, &u.u_cru);
120 for (q = proc; q < procNPROC; q++)
121 if (q->p_pptr == p) {
122 if (q->p_osptr)
123 q->p_osptr->p_ysptr = q->p_ysptr;
124 if (q->p_ysptr)
125 q->p_ysptr->p_osptr = q->p_osptr;
126 if (proc[1].p_cptr)
127 proc[1].p_cptr->p_ysptr = q;
128 q->p_osptr = proc[1].p_cptr;
129 q->p_ysptr = NULL;
130 proc[1].p_cptr = q;
131
132 q->p_pptr = &proc[1];
133 q->p_ppid = 1;
134 wakeup((caddr_t)&proc[1]);
135 /*
136 * Traced processes are killed
137 * since their existence means someone is screwing up.
138 * Stopped processes are sent a hangup and a continue.
139 * This is designed to be ``safe'' for setuid
140 * processes since they must be willing to tolerate
141 * hangups anyways.
142 */
143 if (q->p_flag&STRC) {
144 q->p_flag &= ~STRC;
145 psignal(q, SIGKILL);
146 } else if (q->p_stat == SSTOP) {
147 psignal(q, SIGHUP);
148 psignal(q, SIGCONT);
149 }
150 /*
151 * Protect this process from future
152 * tty signals, clear TSTP/TTIN/TTOU if pending.
153 */
154 (void) spgrp(q, -1);
155 }
156 psignal(p->p_pptr, SIGCHLD);
157 wakeup((caddr_t)p->p_pptr);
158 swtch();
159}
160
161wait()
162{
163 struct rusage ru, *rup;
164
165 if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
166 u.u_error = wait1(0, (struct rusage *)0);
167 return;
168 }
169 rup = (struct rusage *)u.u_ar0[R1];
170 u.u_error = wait1(u.u_ar0[R0], &ru);
171 if (u.u_error)
172 return;
173 (void) copyout((caddr_t)&ru, (caddr_t)rup, sizeof (struct rusage));
174}
175
a8560fa0
SL
176/*
177 * Wait system call.
178 * Search for a terminated (zombie) child,
179 * finally lay it to rest, and collect its status.
180 * Look also for stopped (traced) children,
181 * and pass back status from them.
182 */
183wait1(options, ru)
184 register int options;
185 struct rusage *ru;
186{
187 register f;
188 register struct proc *p, *q;
189
190 f = 0;
191loop:
192 for (p = proc; p < procNPROC; p++)
193 if (p->p_pptr == u.u_procp) {
194 f++;
195 if (p->p_stat == SZOMB) {
196 u.u_r.r_val1 = p->p_pid;
197 u.u_r.r_val2 = p->p_xstat;
198 p->p_xstat = 0;
199 if (ru)
200 *ru = *p->p_ru;
201 ruadd(&u.u_cru, p->p_ru);
202 (void) m_free(dtom(p->p_ru));
203 p->p_ru = 0;
204 p->p_stat = NULL;
205 p->p_pid = 0;
206 p->p_ppid = 0;
207 if (q = p->p_ysptr)
208 q->p_osptr = p->p_osptr;
209 if (q = p->p_osptr)
210 q->p_ysptr = p->p_ysptr;
211 if ((q = p->p_pptr)->p_cptr == p)
212 q->p_cptr = p->p_osptr;
213 p->p_pptr = 0;
214 p->p_ysptr = 0;
215 p->p_osptr = 0;
216 p->p_cptr = 0;
217 p->p_sig = 0;
dd012d1e
SL
218 p->p_sigcatch = 0;
219 p->p_sigignore = 0;
220 p->p_sigmask = 0;
a8560fa0
SL
221 p->p_pgrp = 0;
222 p->p_flag = 0;
223 p->p_wchan = 0;
224 p->p_cursig = 0;
225 return (0);
226 }
227 if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 &&
228 (p->p_flag&STRC || options&WUNTRACED)) {
229 p->p_flag |= SWTED;
230 u.u_r.r_val1 = p->p_pid;
231 u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED;
232 return (0);
233 }
234 }
dd012d1e 235 if (f == 0)
a8560fa0 236 return (ECHILD);
a8560fa0
SL
237 if (options&WNOHANG) {
238 u.u_r.r_val1 = 0;
239 return (0);
240 }
dd012d1e 241 if ((u.u_procp->p_flag&SOUSIG) == 0 && setjmp(&u.u_qsave)) {
a8560fa0
SL
242 u.u_eosys = RESTARTSYS;
243 return (0);
244 }
245 sleep((caddr_t)u.u_procp, PWAIT);
246 goto loop;
247}