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