xref: /original-bsd/sys/kern/kern_fork.c (revision 74d2773b)
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.24 (Berkeley) 02/11/91
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "map.h"
13 #include "user.h"
14 #include "filedesc.h"
15 #include "kernel.h"
16 #include "proc.h"
17 #include "vnode.h"
18 #include "seg.h"
19 #include "file.h"
20 #include "acct.h"
21 #include "ktrace.h"
22 
23 #include "machine/reg.h"
24 #include "machine/psl.h"
25 
26 /*
27  * fork system call.
28  */
29 /* ARGSUSED */
30 fork(p, uap, retval)
31 	struct proc *p;
32 	struct args *uap;
33 	int retval[];
34 {
35 	int error;
36 
37 	return (fork1(p, 0, retval));
38 }
39 
40 /* ARGSUSED */
41 vfork(p, uap, retval)
42 	struct proc *p;
43 	struct args *uap;
44 	int retval[];
45 {
46 
47 	return (fork1(p, 1, retval));
48 }
49 
50 fork1(p1, isvfork, retval)
51 	register struct proc *p1;
52 	int isvfork, retval[];
53 {
54 	register struct proc *p2;
55 	register int a;
56 
57 	a = 0;
58 	if (p1->p_uid != 0) {
59 		for (p2 = allproc; p2; p2 = p2->p_nxt)
60 			if (p2->p_uid == p1->p_uid)
61 				a++;
62 		for (p2 = zombproc; p2; p2 = p2->p_nxt)
63 			if (p2->p_uid == p1->p_uid)
64 				a++;
65 	}
66 	/*
67 	 * Disallow if
68 	 *  No processes at all;
69 	 *  not su and too many procs owned; or
70 	 *  not su and would take last slot.
71 	 */
72 	p2 = freeproc;
73 	if (p2==NULL)
74 		tablefull("proc");
75 	if (p2 == NULL ||
76 	    (p1->p_uid != 0 && (p2->p_nxt == NULL || a > MAXUPRC))) {
77 		retval[1] = 0;
78 		return (EAGAIN);
79 	}
80 	if (newproc(isvfork)) {
81 		retval[0] = p1->p_pid;
82 		retval[1] = 1;  /* child */
83 		u.u_acflag = AFORK;
84 		return (0);
85 	}
86 	retval[0] = p2->p_pid;
87 	retval[1] = 0;
88 	return (0);
89 }
90 
91 /*
92  * Create a new process-- the internal version of
93  * sys fork.
94  * It returns 1 in the new process, 0 in the old.
95  */
96 newproc(isvfork)
97 	int isvfork;
98 {
99 	register struct proc *rpp, *rip;
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_svuid = rip->p_svuid;
174 	rpp->p_rgid = rip->p_rgid;
175 	rpp->p_svgid = rip->p_svgid;
176 	rpp->p_pgrp = rip->p_pgrp;
177 	rpp->p_pgrpnxt = rip->p_pgrpnxt;
178 	rip->p_pgrpnxt = rpp;
179 	rpp->p_nice = rip->p_nice;
180 	rpp->p_pid = mpid;
181 	rpp->p_ppid = rip->p_pid;
182 	rpp->p_pptr = rip;
183 	rpp->p_osptr = rip->p_cptr;
184 	if (rip->p_cptr)
185 		rip->p_cptr->p_ysptr = rpp;
186 	rpp->p_ysptr = NULL;
187 	rpp->p_cptr = NULL;
188 	rip->p_cptr = rpp;
189 	rpp->p_time = 0;
190 	bzero((caddr_t)&rpp->p_utime, sizeof (struct timeval));
191 	bzero((caddr_t)&rpp->p_stime, sizeof (struct timeval));
192 	rpp->p_cpu = 0;
193 	rpp->p_sigmask = rip->p_sigmask;
194 	rpp->p_sigcatch = rip->p_sigcatch;
195 	rpp->p_sigignore = rip->p_sigignore;
196 #ifdef KTRACE
197 	if (rip->p_traceflag&KTRFAC_INHERIT) {
198 		rpp->p_traceflag = rip->p_traceflag;
199 		if ((rpp->p_tracep = rip->p_tracep) != NULL)
200 			VREF(rpp->p_tracep);
201 	} else {
202 		rpp->p_tracep = NULL;
203 		rpp->p_traceflag = 0;
204 	}
205 #endif
206 	rpp->p_rssize = 0;
207 	rpp->p_maxrss = rip->p_maxrss;
208 	rpp->p_wchan = 0;
209 	rpp->p_slptime = 0;
210 	rpp->p_pctcpu = 0;
211 	rpp->p_cpticks = 0;
212 	{
213 	struct proc **hash = &pidhash[PIDHASH(rpp->p_pid)];
214 
215 	rpp->p_hash = *hash;
216 	*hash = rpp;
217 	}
218 
219 	/*
220 	 * Increase reference counts on shared objects.
221 	 */
222 	rpp->p_fd = fddup(rip->p_fd, 0);
223 #ifdef SYSVSHM
224 	if (rip->p_shm)
225 		shmfork(rip, rpp, isvfork);
226 #endif
227 	crhold(u.u_cred);
228 
229 	/*
230 	 * This begins the section where we must prevent the parent
231 	 * from being swapped.
232 	 */
233 	rip->p_flag |= SKEEP;
234 	if (procdup(rpp, isvfork)) {
235 		(void) splclock();
236 		u.u_start = time;
237 		(void) spl0();
238 		return (1);
239 	}
240 
241 	/*
242 	 * Make child runnable and add to run queue.
243 	 */
244 	(void) splclock();
245 	rpp->p_stat = SRUN;
246 	setrq(rpp);
247 	(void) spl0();
248 
249 	/*
250 	 * Cause child to take a non-local goto as soon as it runs.
251 	 * On older systems this was done with SSWAP bit in proc
252 	 * table; on VAX we use u.u_pcb.pcb_sswap so don't need
253 	 * to do rpp->p_flag |= SSWAP.  Actually do nothing here.
254 	 */
255 	/* rpp->p_flag |= SSWAP; */
256 
257 	/*
258 	 * Now can be swapped.
259 	 */
260 	rip->p_flag &= ~SKEEP;
261 
262 	/*
263 	 * XXX preserve synchronization semantics of vfork
264 	 */
265 	if (isvfork) {
266 		u.u_procp->p_flag |= SNOVM;
267 		while (rpp->p_flag & SVFORK)
268 			sleep((caddr_t)rpp, PZERO - 1);
269 		if ((rpp->p_flag & SLOAD) == 0)
270 			panic("newproc vfork");
271 		u.u_procp->p_flag &= ~SNOVM;
272 		rpp->p_flag |= SVFDONE;
273 		wakeup((caddr_t)rpp);
274 	}
275 
276 	/*
277 	 * 0 return means parent.
278 	 */
279 	return (0);
280 }
281