minor formatting and comment changes; removed some old #if 0'd code.
[unix-history] / sys / kern / kern_fork.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
600f7f07 33 * from: @(#)kern_fork.c 7.29 (Berkeley) 5/15/91
41aefbec 34 * $Id: kern_fork.c,v 1.6 1993/12/19 00:51:25 wollman Exp $
15637ed4
RG
35 */
36
37#include "param.h"
38#include "systm.h"
39#include "filedesc.h"
40#include "kernel.h"
41#include "malloc.h"
42#include "proc.h"
43#include "resourcevar.h"
44#include "vnode.h"
45#include "file.h"
46#include "acct.h"
47#include "ktrace.h"
48#include "vm/vm.h"
49
fde1aeb2
GW
50static int fork1(struct proc *, int, int *);
51
15637ed4 52/* ARGSUSED */
4c45483e 53int
15637ed4
RG
54fork(p, uap, retval)
55 struct proc *p;
56 void *uap;
57 int retval[];
58{
59
60 return (fork1(p, 0, retval));
61}
62
63/* ARGSUSED */
4c45483e 64int
15637ed4
RG
65vfork(p, uap, retval)
66 struct proc *p;
67 void *uap;
68 int retval[];
69{
70
71 return (fork1(p, 1, retval));
72}
73
74int nprocs = 1; /* process 0 */
75
fde1aeb2 76static int
15637ed4
RG
77fork1(p1, isvfork, retval)
78 register struct proc *p1;
79 int isvfork, retval[];
80{
81 register struct proc *p2;
82 register int count, uid;
83 static int nextpid, pidchecked = 0;
84
85 count = 0;
86 if ((uid = p1->p_ucred->cr_uid) != 0) {
87 for (p2 = allproc; p2; p2 = p2->p_nxt)
88 if (p2->p_ucred->cr_uid == uid)
89 count++;
90 for (p2 = zombproc; p2; p2 = p2->p_nxt)
91 if (p2->p_ucred->cr_uid == uid)
92 count++;
93 }
94 /*
95 * Although process entries are dynamically entries,
96 * we still keep a global limit on the maximum number
97 * we will create. Don't allow a nonprivileged user
98 * to exceed its current limit or to bring us within one
99 * of the global limit; don't let root exceed the limit.
100 * nprocs is the current number of processes,
101 * maxproc is the limit.
102 */
103 if (nprocs >= maxproc || uid == 0 && nprocs >= maxproc + 1) {
104 tablefull("proc");
105 return (EAGAIN);
106 }
107 if (count > p1->p_rlimit[RLIMIT_NPROC].rlim_cur)
108 return (EAGAIN);
109
110 /*
111 * Find an unused process ID.
112 * We remember a range of unused IDs ready to use
113 * (from nextpid+1 through pidchecked-1).
114 */
115 nextpid++;
116retry:
117 /*
118 * If the process ID prototype has wrapped around,
119 * restart somewhat above 0, as the low-numbered procs
120 * tend to include daemons that don't exit.
121 */
122 if (nextpid >= PID_MAX) {
123 nextpid = 100;
124 pidchecked = 0;
125 }
126 if (nextpid >= pidchecked) {
127 int doingzomb = 0;
128
129 pidchecked = PID_MAX;
130 /*
131 * Scan the active and zombie procs to check whether this pid
132 * is in use. Remember the lowest pid that's greater
133 * than nextpid, so we can avoid checking for a while.
134 */
135 p2 = allproc;
136again:
137 for (; p2 != NULL; p2 = p2->p_nxt) {
138 if (p2->p_pid == nextpid ||
139 p2->p_pgrp->pg_id == nextpid) {
140 nextpid++;
141 if (nextpid >= pidchecked)
142 goto retry;
143 }
144 if (p2->p_pid > nextpid && pidchecked > p2->p_pid)
145 pidchecked = p2->p_pid;
146 if (p2->p_pgrp->pg_id > nextpid &&
147 pidchecked > p2->p_pgrp->pg_id)
148 pidchecked = p2->p_pgrp->pg_id;
149 }
150 if (!doingzomb) {
151 doingzomb = 1;
152 p2 = zombproc;
153 goto again;
154 }
155 }
156
157
158 /*
159 * Allocate new proc.
160 * Link onto allproc (this should probably be delayed).
161 */
162 MALLOC(p2, struct proc *, sizeof(struct proc), M_PROC, M_WAITOK);
163 nprocs++;
a9d36f61
DG
164
165 /* Initialize all fields to zero */
166 bzero((struct proc *)p2, sizeof(struct proc));
167
15637ed4
RG
168 p2->p_nxt = allproc;
169 p2->p_nxt->p_prev = &p2->p_nxt; /* allproc is never NULL */
170 p2->p_prev = &allproc;
171 allproc = p2;
15637ed4
RG
172
173 /*
174 * Make a proc table entry for the new process.
a9d36f61 175 * Copy the section that is copied directly from the parent.
15637ed4 176 */
15637ed4
RG
177 bcopy(&p1->p_startcopy, &p2->p_startcopy,
178 (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy));
15637ed4
RG
179
180 /*
181 * Duplicate sub-structures as needed.
182 * Increase reference counts on shared objects.
183 * The p_stats and p_sigacts substructs are set in vm_fork.
184 */
185 MALLOC(p2->p_cred, struct pcred *, sizeof(struct pcred),
186 M_SUBPROC, M_WAITOK);
187 bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred));
188 p2->p_cred->p_refcnt = 1;
189 crhold(p1->p_ucred);
190
191 p2->p_fd = fdcopy(p1);
192 /*
193 * If p_limit is still copy-on-write, bump refcnt,
194 * otherwise get a copy that won't be modified.
195 * (If PL_SHAREMOD is clear, the structure is shared
196 * copy-on-write.)
197 */
198 if (p1->p_limit->p_lflags & PL_SHAREMOD)
199 p2->p_limit = limcopy(p1->p_limit);
200 else {
201 p2->p_limit = p1->p_limit;
202 p2->p_limit->p_refcnt++;
203 }
204
205 p2->p_flag = SLOAD | (p1->p_flag & SHPUX);
206 if (p1->p_session->s_ttyvp != NULL && p1->p_flag & SCTTY)
207 p2->p_flag |= SCTTY;
208 if (isvfork)
209 p2->p_flag |= SPPWAIT;
210 p2->p_stat = SIDL;
211 p2->p_pid = nextpid;
212 {
213 struct proc **hash = &pidhash[PIDHASH(p2->p_pid)];
214
215 p2->p_hash = *hash;
216 *hash = p2;
217 }
218 p2->p_pgrpnxt = p1->p_pgrpnxt;
219 p1->p_pgrpnxt = p2;
220 p2->p_pptr = p1;
221 p2->p_osptr = p1->p_cptr;
222 if (p1->p_cptr)
223 p1->p_cptr->p_ysptr = p2;
224 p1->p_cptr = p2;
225#ifdef KTRACE
226 /*
227 * Copy traceflag and tracefile if enabled.
228 * If not inherited, these were zeroed above.
229 */
230 if (p1->p_traceflag&KTRFAC_INHERIT) {
231 p2->p_traceflag = p1->p_traceflag;
232 if ((p2->p_tracep = p1->p_tracep) != NULL)
233 VREF(p2->p_tracep);
234 }
235#endif
236
237#if defined(tahoe)
238 p2->p_vmspace->p_ckey = p1->p_vmspace->p_ckey; /* XXX move this */
239#endif
240
41aefbec
DG
241 /*
242 * set priority of child to be that of parent
243 */
244 p2->p_cpu = p1->p_cpu;
245
15637ed4
RG
246 /*
247 * This begins the section where we must prevent the parent
248 * from being swapped.
249 */
250 p1->p_flag |= SKEEP;
251 /*
252 * Set return values for child before vm_fork,
253 * so they can be copied to child stack.
254 * We return parent pid, and mark as child in retval[1].
255 * NOTE: the kernel stack may be at a different location in the child
256 * process, and thus addresses of automatic variables (including retval)
257 * may be invalid after vm_fork returns in the child process.
258 */
259 retval[0] = p1->p_pid;
260 retval[1] = 1;
261 if (vm_fork(p1, p2, isvfork)) {
262 /*
263 * Child process. Set start time and get to work.
264 */
265 (void) splclock();
266 p2->p_stats->p_start = time;
267 (void) spl0();
268 p2->p_acflag = AFORK;
41aefbec
DG
269/*
270 vm_map_init_pmap(&p2->p_vmspace->vm_map);
271*/
15637ed4
RG
272 return (0);
273 }
274
275 /*
276 * Make child runnable and add to run queue.
277 */
278 (void) splhigh();
279 p2->p_stat = SRUN;
280 setrq(p2);
281 (void) spl0();
282
283 /*
284 * Now can be swapped.
285 */
286 p1->p_flag &= ~SKEEP;
287
288 /*
289 * Preserve synchronization semantics of vfork.
290 * If waiting for child to exec or exit, set SPPWAIT
291 * on child, and sleep on our proc (in case of exit).
292 */
293 if (isvfork)
294 while (p2->p_flag & SPPWAIT)
295 tsleep((caddr_t)p1, PWAIT, "ppwait", 0);
296
297 /*
298 * Return child pid to parent process,
299 * marking us as parent via retval[1].
300 */
301 retval[0] = p2->p_pid;
302 retval[1] = 0;
303 return (0);
304}