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