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