|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)kern_fork.c 7.20 (Berkeley) 7/27/90
21: */
22:
23: #include "param.h"
24: #include "systm.h"
25: #include "map.h"
26: #include "user.h"
27: #include "kernel.h"
28: #include "proc.h"
29: #include "vnode.h"
30: #include "seg.h"
31: #include "vm.h"
32: #include "text.h"
33: #include "file.h"
34: #include "acct.h"
35: #include "ktrace.h"
36: #include "../ufs/quota.h"
37:
38: #include "machine/reg.h"
39: #include "machine/pte.h"
40: #include "machine/psl.h"
41:
42: /*
43: * fork system call.
44: */
45: /* ARGSUSED */
46: fork(p, uap, retval)
47: struct proc *p;
48: struct args *uap;
49: int retval[];
50: {
51: int error;
52:
53: u.u_cdmap = zdmap;
54: u.u_csmap = zdmap;
55: if (error = swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap)) {
56: retval[1] = 0;
57: return (error);
58: }
59: return (fork1(p, 0, retval));
60: }
61:
62: /* ARGSUSED */
63: vfork(p, uap, retval)
64: struct proc *p;
65: struct args *uap;
66: int retval[];
67: {
68:
69: return (fork1(p, 1, retval));
70: }
71:
72: fork1(p1, isvfork, retval)
73: register struct proc *p1;
74: int isvfork, retval[];
75: {
76: register struct proc *p2;
77: register int a;
78:
79: a = 0;
80: if (p1->p_uid != 0) {
81: for (p2 = allproc; p2; p2 = p2->p_nxt)
82: if (p2->p_uid == p1->p_uid)
83: a++;
84: for (p2 = zombproc; p2; p2 = p2->p_nxt)
85: if (p2->p_uid == p1->p_uid)
86: a++;
87: }
88: /*
89: * Disallow if
90: * No processes at all;
91: * not su and too many procs owned; or
92: * not su and would take last slot.
93: */
94: p2 = freeproc;
95: if (p2==NULL)
96: tablefull("proc");
97: if (p2 == NULL ||
98: (p1->p_uid != 0 && (p2->p_nxt == NULL || a > MAXUPRC))) {
99: if (!isvfork) {
100: (void) vsexpand((segsz_t)0, &u.u_cdmap, 1);
101: (void) vsexpand((segsz_t)0, &u.u_csmap, 1);
102: }
103: retval[1] = 0;
104: return (EAGAIN);
105: }
106: if (newproc(isvfork)) {
107: retval[0] = p1->p_pid;
108: retval[1] = 1; /* child */
109: u.u_acflag = AFORK;
110: return (0);
111: }
112: retval[0] = p2->p_pid;
113: retval[1] = 0;
114: return (0);
115: }
116:
117: /*
118: * Create a new process-- the internal version of
119: * sys fork.
120: * It returns 1 in the new process, 0 in the old.
121: */
122: newproc(isvfork)
123: int isvfork;
124: {
125: register struct proc *rpp, *rip;
126: register int n;
127: register struct file *fp;
128: static int pidchecked = 0;
129:
130: /*
131: * First, just locate a slot for a process
132: * and copy the useful info from this process into it.
133: * The panic "cannot happen" because fork has already
134: * checked for the existence of a slot.
135: */
136: mpid++;
137: retry:
138: if (mpid >= PID_MAX) {
139: mpid = 100;
140: pidchecked = 0;
141: }
142: if (mpid >= pidchecked) {
143: int doingzomb = 0;
144:
145: pidchecked = PID_MAX;
146: /*
147: * Scan the proc table to check whether this pid
148: * is in use. Remember the lowest pid that's greater
149: * than mpid, so we can avoid checking for a while.
150: */
151: rpp = allproc;
152: again:
153: for (; rpp != NULL; rpp = rpp->p_nxt) {
154: if (rpp->p_pid == mpid || rpp->p_pgrp->pg_id == mpid) {
155: mpid++;
156: if (mpid >= pidchecked)
157: goto retry;
158: }
159: if (rpp->p_pid > mpid && pidchecked > rpp->p_pid)
160: pidchecked = rpp->p_pid;
161: if (rpp->p_pgrp->pg_id > mpid &&
162: pidchecked > rpp->p_pgrp->pg_id)
163: pidchecked = rpp->p_pgrp->pg_id;
164: }
165: if (!doingzomb) {
166: doingzomb = 1;
167: rpp = zombproc;
168: goto again;
169: }
170: }
171: if ((rpp = freeproc) == NULL)
172: panic("no procs");
173:
174: freeproc = rpp->p_nxt; /* off freeproc */
175: rpp->p_nxt = allproc; /* onto allproc */
176: rpp->p_nxt->p_prev = &rpp->p_nxt; /* (allproc is never NULL) */
177: rpp->p_prev = &allproc;
178: allproc = rpp;
179:
180: /*
181: * Make a proc table entry for the new process.
182: */
183: rip = u.u_procp;
184: #if defined(tahoe)
185: rpp->p_ckey = rip->p_ckey;
186: rpp->p_dkey = 0;
187: #endif
188: rpp->p_stat = SIDL;
189: timerclear(&rpp->p_realtimer.it_value);
190: rpp->p_flag = SLOAD | (rip->p_flag & (SPAGV|SHPUX));
191: if (rip->p_session->s_ttyvp != NULL && rip->p_flag & SCTTY)
192: rpp->p_flag |= SCTTY;
193: if (isvfork) {
194: rpp->p_flag |= SVFORK;
195: rpp->p_ndx = rip->p_ndx;
196: } else
197: rpp->p_ndx = rpp - proc;
198: bcopy(rip->p_comm, rpp->p_comm, MAXCOMLEN+1);
199: bcopy(rip->p_logname, rpp->p_logname, MAXLOGNAME);
200: rpp->p_uid = rip->p_uid;
201: rpp->p_ruid = rip->p_ruid;
202: rpp->p_rgid = rip->p_rgid;
203: rpp->p_pgrp = rip->p_pgrp;
204: rpp->p_pgrpnxt = rip->p_pgrpnxt;
205: rip->p_pgrpnxt = rpp;
206: rpp->p_nice = rip->p_nice;
207: rpp->p_textp = isvfork ? 0 : rip->p_textp;
208: rpp->p_pid = mpid;
209: rpp->p_ppid = rip->p_pid;
210: rpp->p_pptr = rip;
211: rpp->p_osptr = rip->p_cptr;
212: if (rip->p_cptr)
213: rip->p_cptr->p_ysptr = rpp;
214: rpp->p_ysptr = NULL;
215: rpp->p_cptr = NULL;
216: rip->p_cptr = rpp;
217: rpp->p_time = 0;
218: bzero((caddr_t)&rpp->p_utime, sizeof (struct timeval));
219: bzero((caddr_t)&rpp->p_stime, sizeof (struct timeval));
220: rpp->p_cpu = 0;
221: rpp->p_sigmask = rip->p_sigmask;
222: rpp->p_sigcatch = rip->p_sigcatch;
223: rpp->p_sigignore = rip->p_sigignore;
224: /* take along any pending signals like stops? */
225: if (isvfork) {
226: rpp->p_tsize = rpp->p_dsize = rpp->p_mmsize = rpp->p_ssize = 0;
227: rpp->p_szpt = clrnd(ctopt(HIGHPAGES));
228: forkstat.cntvfork++;
229: forkstat.sizvfork += rip->p_dsize + rip->p_ssize;
230: } else {
231: rpp->p_tsize = rip->p_tsize;
232: rpp->p_dsize = rip->p_dsize;
233: rpp->p_mmsize = rip->p_mmsize;
234: rpp->p_ssize = rip->p_ssize;
235: rpp->p_szpt = rip->p_szpt;
236: forkstat.cntfork++;
237: forkstat.sizfork += rip->p_dsize + rip->p_ssize;
238: }
239: #ifdef KTRACE
240: if (rip->p_traceflag&KTRFAC_INHERIT) {
241: rpp->p_traceflag = rip->p_traceflag;
242: if ((rpp->p_tracep = rip->p_tracep) != NULL)
243: VREF(rpp->p_tracep);
244: } else {
245: rpp->p_tracep = NULL;
246: rpp->p_traceflag = 0;
247: }
248: #endif
249: rpp->p_rssize = 0;
250: rpp->p_maxrss = rip->p_maxrss;
251: rpp->p_wchan = 0;
252: rpp->p_slptime = 0;
253: rpp->p_pctcpu = 0;
254: rpp->p_cpticks = 0;
255: {
256: struct proc **hash = &pidhash[PIDHASH(rpp->p_pid)];
257:
258: rpp->p_hash = *hash;
259: *hash = rpp;
260: }
261: multprog++;
262:
263: /*
264: * Increase reference counts on shared objects.
265: */
266: for (n = 0; n <= u.u_lastfile; n++) {
267: fp = u.u_ofile[n];
268: if (fp == NULL)
269: continue;
270: fp->f_count++;
271: }
272: VREF(u.u_cdir);
273: if (u.u_rdir)
274: VREF(u.u_rdir);
275: crhold(u.u_cred);
276:
277: /*
278: * This begins the section where we must prevent the parent
279: * from being swapped.
280: */
281: rip->p_flag |= SKEEP;
282: if (procdup(rpp, isvfork)) {
283: (void) splclock();
284: u.u_start = time;
285: (void) spl0();
286: return (1);
287: }
288:
289: /*
290: * Make child runnable and add to run queue.
291: */
292: (void) splclock();
293: rpp->p_stat = SRUN;
294: setrq(rpp);
295: (void) spl0();
296:
297: /*
298: * Cause child to take a non-local goto as soon as it runs.
299: * On older systems this was done with SSWAP bit in proc
300: * table; on VAX we use u.u_pcb.pcb_sswap so don't need
301: * to do rpp->p_flag |= SSWAP. Actually do nothing here.
302: */
303: /* rpp->p_flag |= SSWAP; */
304:
305: /*
306: * Now can be swapped.
307: */
308: rip->p_flag &= ~SKEEP;
309:
310: /*
311: * If vfork make chain from parent process to child
312: * (where virtal memory is temporarily). Wait for
313: * child to finish, steal virtual memory back,
314: * and wakeup child to let it die.
315: */
316: if (isvfork) {
317: u.u_procp->p_xlink = rpp;
318: u.u_procp->p_flag |= SNOVM;
319: while (rpp->p_flag & SVFORK)
320: sleep((caddr_t)rpp, PZERO - 1);
321: if ((rpp->p_flag & SLOAD) == 0)
322: panic("newproc vfork");
323: uaccess(rpp, Vfmap, &vfutl);
324: u.u_procp->p_xlink = 0;
325: vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap);
326: u.u_procp->p_flag &= ~SNOVM;
327: rpp->p_ndx = rpp - proc;
328: rpp->p_flag |= SVFDONE;
329: wakeup((caddr_t)rpp);
330: }
331:
332: /*
333: * 0 return means parent.
334: */
335: return (0);
336: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.