xref: /original-bsd/sys/kern/kern_fork.c (revision dd262573)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)kern_fork.c	7.22 (Berkeley) 12/05/90
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "map.h"
13 #include "user.h"
14 #include "kernel.h"
15 #include "proc.h"
16 #include "vnode.h"
17 #include "seg.h"
18 #include "file.h"
19 #include "acct.h"
20 #include "ktrace.h"
21 
22 #include "machine/reg.h"
23 #include "machine/psl.h"
24 
25 /*
26  * fork system call.
27  */
28 /* ARGSUSED */
29 fork(p, uap, retval)
30 	struct proc *p;
31 	struct args *uap;
32 	int retval[];
33 {
34 	int error;
35 
36 	return (fork1(p, 0, retval));
37 }
38 
39 /* ARGSUSED */
40 vfork(p, uap, retval)
41 	struct proc *p;
42 	struct args *uap;
43 	int retval[];
44 {
45 
46 	return (fork1(p, 1, retval));
47 }
48 
49 fork1(p1, isvfork, retval)
50 	register struct proc *p1;
51 	int isvfork, retval[];
52 {
53 	register struct proc *p2;
54 	register int a;
55 
56 	a = 0;
57 	if (p1->p_uid != 0) {
58 		for (p2 = allproc; p2; p2 = p2->p_nxt)
59 			if (p2->p_uid == p1->p_uid)
60 				a++;
61 		for (p2 = zombproc; p2; p2 = p2->p_nxt)
62 			if (p2->p_uid == p1->p_uid)
63 				a++;
64 	}
65 	/*
66 	 * Disallow if
67 	 *  No processes at all;
68 	 *  not su and too many procs owned; or
69 	 *  not su and would take last slot.
70 	 */
71 	p2 = freeproc;
72 	if (p2==NULL)
73 		tablefull("proc");
74 	if (p2 == NULL ||
75 	    (p1->p_uid != 0 && (p2->p_nxt == NULL || a > MAXUPRC))) {
76 		retval[1] = 0;
77 		return (EAGAIN);
78 	}
79 	if (newproc(isvfork)) {
80 		retval[0] = p1->p_pid;
81 		retval[1] = 1;  /* child */
82 		u.u_acflag = AFORK;
83 		return (0);
84 	}
85 	retval[0] = p2->p_pid;
86 	retval[1] = 0;
87 	return (0);
88 }
89 
90 /*
91  * Create a new process-- the internal version of
92  * sys fork.
93  * It returns 1 in the new process, 0 in the old.
94  */
95 newproc(isvfork)
96 	int isvfork;
97 {
98 	register struct proc *rpp, *rip;
99 	register int n;
100 	register struct file *fp;
101 	static int pidchecked = 0;
102 
103 	/*
104 	 * First, just locate a slot for a process
105 	 * and copy the useful info from this process into it.
106 	 * The panic "cannot happen" because fork has already
107 	 * checked for the existence of a slot.
108 	 */
109 	mpid++;
110 retry:
111 	if (mpid >= PID_MAX) {
112 		mpid = 100;
113 		pidchecked = 0;
114 	}
115 	if (mpid >= pidchecked) {
116 		int doingzomb = 0;
117 
118 		pidchecked = PID_MAX;
119 		/*
120 		 * Scan the proc table to check whether this pid
121 		 * is in use.  Remember the lowest pid that's greater
122 		 * than mpid, so we can avoid checking for a while.
123 		 */
124 		rpp = allproc;
125 again:
126 		for (; rpp != NULL; rpp = rpp->p_nxt) {
127 			if (rpp->p_pid == mpid || rpp->p_pgrp->pg_id == mpid) {
128 				mpid++;
129 				if (mpid >= pidchecked)
130 					goto retry;
131 			}
132 			if (rpp->p_pid > mpid && pidchecked > rpp->p_pid)
133 				pidchecked = rpp->p_pid;
134 			if (rpp->p_pgrp->pg_id > mpid &&
135 			    pidchecked > rpp->p_pgrp->pg_id)
136 				pidchecked = rpp->p_pgrp->pg_id;
137 		}
138 		if (!doingzomb) {
139 			doingzomb = 1;
140 			rpp = zombproc;
141 			goto again;
142 		}
143 	}
144 	if ((rpp = freeproc) == NULL)
145 		panic("no procs");
146 
147 	freeproc = rpp->p_nxt;			/* off freeproc */
148 	rpp->p_nxt = allproc;			/* onto allproc */
149 	rpp->p_nxt->p_prev = &rpp->p_nxt;	/*   (allproc is never NULL) */
150 	rpp->p_prev = &allproc;
151 	allproc = rpp;
152 
153 	/*
154 	 * Make a proc table entry for the new process.
155 	 */
156 	rip = u.u_procp;
157 #if defined(tahoe)
158 	rpp->p_ckey = rip->p_ckey;
159 	rpp->p_dkey = 0;
160 #endif
161 	rpp->p_stat = SIDL;
162 	timerclear(&rpp->p_realtimer.it_value);
163 	rpp->p_flag = SLOAD | (rip->p_flag & (SPAGV|SHPUX));
164 	if (rip->p_session->s_ttyvp != NULL && rip->p_flag & SCTTY)
165 		rpp->p_flag |= SCTTY;
166 	if (isvfork)
167 		rpp->p_flag |= SVFORK;
168 	rpp->p_ndx = rpp - proc;
169 	bcopy(rip->p_comm, rpp->p_comm, MAXCOMLEN+1);
170 	bcopy(rip->p_logname, rpp->p_logname, MAXLOGNAME);
171 	rpp->p_uid = rip->p_uid;
172 	rpp->p_ruid = rip->p_ruid;
173 	rpp->p_rgid = rip->p_rgid;
174 	rpp->p_pgrp = rip->p_pgrp;
175 	rpp->p_pgrpnxt = rip->p_pgrpnxt;
176 	rip->p_pgrpnxt = rpp;
177 	rpp->p_nice = rip->p_nice;
178 	rpp->p_pid = mpid;
179 	rpp->p_ppid = rip->p_pid;
180 	rpp->p_pptr = rip;
181 	rpp->p_osptr = rip->p_cptr;
182 	if (rip->p_cptr)
183 		rip->p_cptr->p_ysptr = rpp;
184 	rpp->p_ysptr = NULL;
185 	rpp->p_cptr = NULL;
186 	rip->p_cptr = rpp;
187 	rpp->p_time = 0;
188 	bzero((caddr_t)&rpp->p_utime, sizeof (struct timeval));
189 	bzero((caddr_t)&rpp->p_stime, sizeof (struct timeval));
190 	rpp->p_cpu = 0;
191 	rpp->p_sigmask = rip->p_sigmask;
192 	rpp->p_sigcatch = rip->p_sigcatch;
193 	rpp->p_sigignore = rip->p_sigignore;
194 #ifdef KTRACE
195 	if (rip->p_traceflag&KTRFAC_INHERIT) {
196 		rpp->p_traceflag = rip->p_traceflag;
197 		if ((rpp->p_tracep = rip->p_tracep) != NULL)
198 			VREF(rpp->p_tracep);
199 	} else {
200 		rpp->p_tracep = NULL;
201 		rpp->p_traceflag = 0;
202 	}
203 #endif
204 	rpp->p_rssize = 0;
205 	rpp->p_maxrss = rip->p_maxrss;
206 	rpp->p_wchan = 0;
207 	rpp->p_slptime = 0;
208 	rpp->p_pctcpu = 0;
209 	rpp->p_cpticks = 0;
210 	{
211 	struct proc **hash = &pidhash[PIDHASH(rpp->p_pid)];
212 
213 	rpp->p_hash = *hash;
214 	*hash = rpp;
215 	}
216 
217 	/*
218 	 * Increase reference counts on shared objects.
219 	 */
220 	for (n = 0; n <= u.u_lastfile; n++) {
221 		fp = u.u_ofile[n];
222 		if (fp == NULL)
223 			continue;
224 		fp->f_count++;
225 	}
226 #ifdef SYSVSHM
227 	if (rip->p_shm)
228 		shmfork(rip, rpp, isvfork);
229 #endif
230 	VREF(u.u_cdir);
231 	if (u.u_rdir)
232 		VREF(u.u_rdir);
233 	crhold(u.u_cred);
234 
235 	/*
236 	 * This begins the section where we must prevent the parent
237 	 * from being swapped.
238 	 */
239 	rip->p_flag |= SKEEP;
240 	if (procdup(rpp, isvfork)) {
241 		(void) splclock();
242 		u.u_start = time;
243 		(void) spl0();
244 		return (1);
245 	}
246 
247 	/*
248 	 * Make child runnable and add to run queue.
249 	 */
250 	(void) splclock();
251 	rpp->p_stat = SRUN;
252 	setrq(rpp);
253 	(void) spl0();
254 
255 	/*
256 	 * Cause child to take a non-local goto as soon as it runs.
257 	 * On older systems this was done with SSWAP bit in proc
258 	 * table; on VAX we use u.u_pcb.pcb_sswap so don't need
259 	 * to do rpp->p_flag |= SSWAP.  Actually do nothing here.
260 	 */
261 	/* rpp->p_flag |= SSWAP; */
262 
263 	/*
264 	 * Now can be swapped.
265 	 */
266 	rip->p_flag &= ~SKEEP;
267 
268 	/*
269 	 * XXX preserve synchronization semantics of vfork
270 	 */
271 	if (isvfork) {
272 		u.u_procp->p_flag |= SNOVM;
273 		while (rpp->p_flag & SVFORK)
274 			sleep((caddr_t)rpp, PZERO - 1);
275 		if ((rpp->p_flag & SLOAD) == 0)
276 			panic("newproc vfork");
277 		u.u_procp->p_flag &= ~SNOVM;
278 		rpp->p_flag |= SVFDONE;
279 		wakeup((caddr_t)rpp);
280 	}
281 
282 	/*
283 	 * 0 return means parent.
284 	 */
285 	return (0);
286 }
287