1: /*
2: * Copyright (c) 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 2.6 (2.11BSD) 2000/2/20
7: */
8:
9: #include "param.h"
10: #include "../machine/psl.h"
11: #include "../machine/reg.h"
12:
13: #include "systm.h"
14: #include "map.h"
15: #include "user.h"
16: #include "proc.h"
17: #include "inode.h"
18: #include "vm.h"
19: #include "file.h"
20: #include "wait.h"
21: #include "kernel.h"
22: #ifdef QUOTA
23: #include "quota.h"
24: #endif
25: #include "ingres.h"
26:
27: extern int Acctopen; /* kern_acct.c */
28:
29: /*
30: * exit system call: pass back caller's arg
31: */
32: rexit()
33: {
34: register struct a {
35: int rval;
36: } *uap = (struct a *)u.u_ap;
37:
38: exit(W_EXITCODE(uap->rval, 0));
39: /* NOTREACHED */
40: }
41:
42: /*
43: * Exit: deallocate address space and other resources,
44: * change proc state to zombie, and unlink proc from allproc
45: * list. Save exit status and rusage for wait4().
46: * Check for child processes and orphan them.
47: */
48: exit(rv)
49: {
50: register int i;
51: register struct proc *p;
52: struct proc **pp;
53:
54: p = u.u_procp;
55: p->p_flag &= ~(P_TRACED|SULOCK);
56: p->p_sigignore = ~0;
57: p->p_sig = 0;
58: /*
59: * 2.11 doesn't need to do this and it gets overwritten anyway.
60: * p->p_realtimer.it_value = 0;
61: */
62: for (i = 0; i <= u.u_lastfile; i++) {
63: register struct file *f;
64:
65: f = u.u_ofile[i];
66: u.u_ofile[i] = NULL;
67: u.u_pofile[i] = 0;
68: (void) closef(f);
69: }
70: ilock(u.u_cdir);
71: iput(u.u_cdir);
72: if (u.u_rdir) {
73: ilock(u.u_rdir);
74: iput(u.u_rdir);
75: }
76: u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
77: if (Acctopen)
78: (void) acct();
79: #ifdef QUOTA
80: QUOTAMAP();
81: qclean();
82: QUOTAUNMAP();
83: #endif
84: /*
85: * Freeing the user structure and kernel stack
86: * for the current process: have to run a bit longer
87: * using the slots which are about to be freed...
88: */
89: if (p->p_flag & SVFORK)
90: endvfork();
91: else {
92: xfree();
93: mfree(coremap, p->p_dsize, p->p_daddr);
94: mfree(coremap, p->p_ssize, p->p_saddr);
95: }
96: mfree(coremap, USIZE, p->p_addr);
97:
98: if (p->p_pid == 1)
99: panic("init died");
100: if (*p->p_prev = p->p_nxt) /* off allproc queue */
101: p->p_nxt->p_prev = p->p_prev;
102: if (p->p_nxt = zombproc) /* onto zombproc */
103: p->p_nxt->p_prev = &p->p_nxt;
104: p->p_prev = &zombproc;
105: zombproc = p;
106: p->p_stat = SZOMB;
107:
108: #if NINGRES > 0
109: ingres_rma(p->p_pid); /* Remove any ingres locks */
110: #endif
111:
112: noproc = 1;
113: for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash)
114: if (*pp == p) {
115: *pp = p->p_hash;
116: goto done;
117: }
118: panic("exit");
119: done:
120: /*
121: * Overwrite p_alive substructure of proc - better not be anything
122: * important left!
123: */
124: p->p_xstat = rv;
125: p->p_ru = u.u_ru;
126: ruadd(&p->p_ru, &u.u_cru);
127: {
128: register struct proc *q;
129: int doingzomb = 0;
130:
131: q = allproc;
132: again:
133: for(; q; q = q->p_nxt)
134: if (q->p_pptr == p) {
135: q->p_pptr = &proc[1];
136: q->p_ppid = 1;
137: wakeup((caddr_t)&proc[1]);
138: if (q->p_flag& P_TRACED) {
139: q->p_flag &= ~P_TRACED;
140: psignal(q, SIGKILL);
141: } else if (q->p_stat == SSTOP) {
142: psignal(q, SIGHUP);
143: psignal(q, SIGCONT);
144: }
145: }
146: if (!doingzomb) {
147: doingzomb = 1;
148: q = zombproc;
149: goto again;
150: }
151: }
152: psignal(p->p_pptr, SIGCHLD);
153: wakeup((caddr_t)p->p_pptr);
154: swtch();
155: /* NOTREACHED */
156: }
157:
158: struct args
159: {
160: int pid;
161: int *status;
162: int options;
163: struct rusage *rusage;
164: int compat;
165: };
166:
167: wait4()
168: {
169: int retval[2];
170: register struct args *uap = (struct args *)u.u_ap;
171:
172: uap->compat = 0;
173: u.u_error = wait1(u.u_procp, uap, retval);
174: if (!u.u_error)
175: u.u_r.r_val1 = retval[0];
176: }
177:
178: /*
179: * Wait: check child processes to see if any have exited,
180: * stopped under trace or (optionally) stopped by a signal.
181: * Pass back status and make available for reuse the exited
182: * child's proc structure.
183: */
184: wait1(q, uap, retval)
185: struct proc *q;
186: register struct args *uap;
187: int retval[];
188: {
189: int nfound, status;
190: struct rusage ru; /* used for local conversion */
191: register struct proc *p;
192: register int error;
193:
194: if (uap->pid == WAIT_MYPGRP) /* == 0 */
195: uap->pid = -q->p_pgrp;
196: loop:
197: nfound = 0;
198: /*
199: * 4.X has child links in the proc structure, so they consolidate
200: * these two tests into one loop. We only have the zombie chain
201: * and the allproc chain, so we check for ZOMBIES first, then for
202: * children that have changed state. We check for ZOMBIES first
203: * because they are more common, and, as the list is typically small,
204: * a faster check.
205: */
206: for (p = zombproc; p;p = p->p_nxt) {
207: if (p->p_pptr != q) /* are we the parent of this process? */
208: continue;
209: if (uap->pid != WAIT_ANY &&
210: p->p_pid != uap->pid && p->p_pgrp != -uap->pid)
211: continue;
212: retval[0] = p->p_pid;
213: retval[1] = p->p_xstat;
214: if (uap->status && (error = copyout(&p->p_xstat, uap->status,
215: sizeof (uap->status))))
216: return(error);
217: if (uap->rusage) {
218: rucvt(&ru, &p->p_ru);
219: if (error = copyout(&ru, uap->rusage, sizeof (ru)))
220: return(error);
221: }
222: ruadd(&u.u_cru, &p->p_ru);
223: p->p_xstat = 0;
224: p->p_stat = NULL;
225: p->p_pid = 0;
226: p->p_ppid = 0;
227: if (*p->p_prev = p->p_nxt) /* off zombproc */
228: p->p_nxt->p_prev = p->p_prev;
229: p->p_nxt = freeproc; /* onto freeproc */
230: freeproc = p;
231: p->p_pptr = 0;
232: p->p_sig = 0;
233: p->p_sigcatch = 0;
234: p->p_sigignore = 0;
235: p->p_sigmask = 0;
236: p->p_pgrp = 0;
237: p->p_flag = 0;
238: p->p_wchan = 0;
239: return (0);
240: }
241: for (p = allproc; p;p = p->p_nxt) {
242: if (p->p_pptr != q)
243: continue;
244: if (uap->pid != WAIT_ANY &&
245: p->p_pid != uap->pid && p->p_pgrp != -uap->pid)
246: continue;
247: ++nfound;
248: if (p->p_stat == SSTOP && (p->p_flag& P_WAITED)==0 &&
249: (p->p_flag&P_TRACED || uap->options&WUNTRACED)) {
250: p->p_flag |= P_WAITED;
251: retval[0] = p->p_pid;
252: error = 0;
253: if (uap->compat)
254: retval[1] = W_STOPCODE(p->p_ptracesig);
255: else if (uap->status) {
256: status = W_STOPCODE(p->p_ptracesig);
257: error = copyout(&status, uap->status,
258: sizeof (status));
259: }
260: return (error);
261: }
262: }
263: if (nfound == 0)
264: return (ECHILD);
265: if (uap->options&WNOHANG) {
266: retval[0] = 0;
267: return (0);
268: }
269: error = tsleep(q, PWAIT|PCATCH, 0);
270: if (error == 0)
271: goto loop;
272: return(error);
273: }
274:
275: /*
276: * Notify parent that vfork child is finished with parent's data. Called
277: * during exit/exec(getxfile); must be called before xfree(). The child
278: * must be locked in core so it will be in core when the parent runs.
279: */
280: endvfork()
281: {
282: register struct proc *rip, *rpp;
283:
284: rpp = u.u_procp;
285: rip = rpp->p_pptr;
286: rpp->p_flag &= ~SVFORK;
287: rpp->p_flag |= SLOCK;
288: wakeup((caddr_t)rpp);
289: while(!(rpp->p_flag&SVFDONE))
290: sleep((caddr_t)rip,PZERO-1);
291: /*
292: * The parent has taken back our data+stack, set our sizes to 0.
293: */
294: u.u_dsize = rpp->p_dsize = 0;
295: u.u_ssize = rpp->p_ssize = 0;
296: rpp->p_flag &= ~(SVFDONE | SLOCK);
297: }
Defined functions
exit
defined in line
48; used 4 times
rexit
defined in line
32; used 2 times
Defined struct's
a
defined in line
34; used 2 times
args
defined in line
158; used 6 times