add memory filesystem initialization
[unix-history] / usr / src / sys / kern / kern_fork.c
CommitLineData
da7c5cc6 1/*
c4ec2128
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
c4ec2128
KM
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 *
20b702d3 17 * @(#)kern_fork.c 7.8 (Berkeley) %G%
da7c5cc6 18 */
50108d5c 19
94368568
JB
20#include "param.h"
21#include "systm.h"
22#include "map.h"
94368568
JB
23#include "user.h"
24#include "kernel.h"
25#include "proc.h"
c4ec2128 26#include "vnode.h"
94368568
JB
27#include "seg.h"
28#include "vm.h"
29#include "text.h"
30#include "file.h"
31#include "acct.h"
c4ec2128 32#include "../ufs/quota.h"
50108d5c 33
d301d150
KM
34#include "machine/reg.h"
35#include "machine/pte.h"
36#include "machine/psl.h"
37
50108d5c
SL
38/*
39 * fork system call.
40 */
41fork()
42{
43
44 u.u_cdmap = zdmap;
45 u.u_csmap = zdmap;
46 if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) {
47 u.u_r.r_val2 = 0;
48 return;
49 }
50 fork1(0);
51}
52
53vfork()
54{
55
56 fork1(1);
57}
58
59fork1(isvfork)
60 int isvfork;
61{
62 register struct proc *p1, *p2;
63 register a;
64
65 a = 0;
1d348849
MK
66 if (u.u_uid != 0) {
67 for (p1 = allproc; p1; p1 = p1->p_nxt)
68 if (p1->p_uid == u.u_uid)
69 a++;
70 for (p1 = zombproc; p1; p1 = p1->p_nxt)
71 if (p1->p_uid == u.u_uid)
50108d5c 72 a++;
50108d5c
SL
73 }
74 /*
75 * Disallow if
76 * No processes at all;
77 * not su and too many procs owned; or
78 * not su and would take last slot.
79 */
1d348849 80 p2 = freeproc;
50108d5c
SL
81 if (p2==NULL)
82 tablefull("proc");
1d348849 83 if (p2==NULL || (u.u_uid!=0 && (p2->p_nxt == NULL || a>MAXUPRC))) {
50108d5c
SL
84 u.u_error = EAGAIN;
85 if (!isvfork) {
8011f5df
MK
86 (void) vsexpand((size_t)0, &u.u_cdmap, 1);
87 (void) vsexpand((size_t)0, &u.u_csmap, 1);
50108d5c
SL
88 }
89 goto out;
90 }
91 p1 = u.u_procp;
92 if (newproc(isvfork)) {
93 u.u_r.r_val1 = p1->p_pid;
94 u.u_r.r_val2 = 1; /* child */
e8109af3 95 u.u_start = time;
50108d5c
SL
96 u.u_acflag = AFORK;
97 return;
98 }
99 u.u_r.r_val1 = p2->p_pid;
100
101out:
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 */
110newproc(isvfork)
111 int isvfork;
112{
50108d5c
SL
113 register struct proc *rpp, *rip;
114 register int n;
115 register struct file *fp;
1d348849 116 static int pidchecked = 0;
50108d5c 117
50108d5c
SL
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 */
50108d5c 124 mpid++;
1d348849 125retry:
50108d5c 126 if (mpid >= 30000) {
1d348849
MK
127 mpid = 100;
128 pidchecked = 0;
50108d5c 129 }
1d348849
MK
130 if (mpid >= pidchecked) {
131 int doingzomb = 0;
e9539440 132
1d348849
MK
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;
140again:
141 for (; rpp != NULL; rpp = rpp->p_nxt) {
8fe87cbb 142 if (rpp->p_pid == mpid || rpp->p_pgrp->pg_id == mpid) {
1d348849
MK
143 mpid++;
144 if (mpid >= pidchecked)
145 goto retry;
146 }
e9539440 147 if (rpp->p_pid > mpid && pidchecked > rpp->p_pid)
1d348849 148 pidchecked = rpp->p_pid;
8fe87cbb
MT
149 if (rpp->p_pgrp->pg_id > mpid &&
150 pidchecked > rpp->p_pgrp->pg_id)
151 pidchecked = rpp->p_pgrp->pg_id;
1d348849
MK
152 }
153 if (!doingzomb) {
154 doingzomb = 1;
155 rpp = zombproc;
156 goto again;
157 }
50108d5c 158 }
1d348849 159 if ((rpp = freeproc) == NULL)
50108d5c
SL
160 panic("no procs");
161
1d348849
MK
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
50108d5c
SL
168 /*
169 * Make a proc table entry for the new process.
170 */
171 rip = u.u_procp;
172#ifdef QUOTA
173 rpp->p_quota = rip->p_quota;
174 rpp->p_quota->q_cnt++;
fb1db32c
MK
175#endif
176#if defined(tahoe)
177 rpp->p_ckey = rip->p_ckey;
178 rpp->p_dkey = 0;
50108d5c
SL
179#endif
180 rpp->p_stat = SIDL;
181 timerclear(&rpp->p_realtimer.it_value);
c4ec2128 182 rpp->p_flag = SLOAD | (rip->p_flag & (SPAGV|SOUSIG));
50108d5c
SL
183 if (isvfork) {
184 rpp->p_flag |= SVFORK;
185 rpp->p_ndx = rip->p_ndx;
186 } else
187 rpp->p_ndx = rpp - proc;
188 rpp->p_uid = rip->p_uid;
189 rpp->p_pgrp = rip->p_pgrp;
8fe87cbb
MT
190 rpp->p_pgrpnxt = rip->p_pgrpnxt;
191 rip->p_pgrpnxt = rpp;
50108d5c
SL
192 rpp->p_nice = rip->p_nice;
193 rpp->p_textp = isvfork ? 0 : rip->p_textp;
194 rpp->p_pid = mpid;
195 rpp->p_ppid = rip->p_pid;
196 rpp->p_pptr = rip;
197 rpp->p_osptr = rip->p_cptr;
198 if (rip->p_cptr)
199 rip->p_cptr->p_ysptr = rpp;
200 rpp->p_ysptr = NULL;
201 rpp->p_cptr = NULL;
202 rip->p_cptr = rpp;
203 rpp->p_time = 0;
204 rpp->p_cpu = 0;
dd012d1e
SL
205 rpp->p_sigmask = rip->p_sigmask;
206 rpp->p_sigcatch = rip->p_sigcatch;
207 rpp->p_sigignore = rip->p_sigignore;
208 /* take along any pending signals like stops? */
50108d5c
SL
209 if (isvfork) {
210 rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0;
211 rpp->p_szpt = clrnd(ctopt(UPAGES));
212 forkstat.cntvfork++;
213 forkstat.sizvfork += rip->p_dsize + rip->p_ssize;
214 } else {
215 rpp->p_tsize = rip->p_tsize;
216 rpp->p_dsize = rip->p_dsize;
217 rpp->p_ssize = rip->p_ssize;
218 rpp->p_szpt = rip->p_szpt;
219 forkstat.cntfork++;
220 forkstat.sizfork += rip->p_dsize + rip->p_ssize;
221 }
98111078
MT
222#ifdef KTRACE
223 if (rip->p_flag&SKTR) {
224 rpp->p_flag |= SKTR;
20b702d3
MT
225 if ((rpp->p_tracep = rip->p_tracep) != NULL)
226 VREF(rpp->p_tracep);
98111078
MT
227 rpp->p_traceflag = rip->p_traceflag;
228 } else {
229 rpp->p_tracep = NULL;
230 rpp->p_traceflag = 0;
231 }
232#endif
50108d5c
SL
233 rpp->p_rssize = 0;
234 rpp->p_maxrss = rip->p_maxrss;
235 rpp->p_wchan = 0;
236 rpp->p_slptime = 0;
237 rpp->p_pctcpu = 0;
238 rpp->p_cpticks = 0;
239 n = PIDHASH(rpp->p_pid);
1d348849 240 rpp->p_idhash = pidhash[n];
50108d5c
SL
241 pidhash[n] = rpp - proc;
242 multprog++;
243
244 /*
245 * Increase reference counts on shared objects.
246 */
8694aaad 247 for (n = 0; n <= u.u_lastfile; n++) {
50108d5c
SL
248 fp = u.u_ofile[n];
249 if (fp == NULL)
250 continue;
251 fp->f_count++;
50108d5c 252 }
8fe1c702 253 VREF(u.u_cdir);
50108d5c 254 if (u.u_rdir)
8fe1c702 255 VREF(u.u_rdir);
c4ec2128 256 crhold(u.u_cred);
50108d5c
SL
257
258 /*
50108d5c
SL
259 * This begins the section where we must prevent the parent
260 * from being swapped.
261 */
262 rip->p_flag |= SKEEP;
263 if (procdup(rpp, isvfork))
264 return (1);
265
266 /*
267 * Make child runnable and add to run queue.
268 */
01b0e233 269 (void) splclock();
50108d5c
SL
270 rpp->p_stat = SRUN;
271 setrq(rpp);
272 (void) spl0();
273
274 /*
275 * Cause child to take a non-local goto as soon as it runs.
276 * On older systems this was done with SSWAP bit in proc
277 * table; on VAX we use u.u_pcb.pcb_sswap so don't need
278 * to do rpp->p_flag |= SSWAP. Actually do nothing here.
279 */
280 /* rpp->p_flag |= SSWAP; */
281
282 /*
283 * Now can be swapped.
284 */
285 rip->p_flag &= ~SKEEP;
286
287 /*
288 * If vfork make chain from parent process to child
289 * (where virtal memory is temporarily). Wait for
290 * child to finish, steal virtual memory back,
291 * and wakeup child to let it die.
292 */
293 if (isvfork) {
294 u.u_procp->p_xlink = rpp;
295 u.u_procp->p_flag |= SNOVM;
296 while (rpp->p_flag & SVFORK)
297 sleep((caddr_t)rpp, PZERO - 1);
298 if ((rpp->p_flag & SLOAD) == 0)
299 panic("newproc vfork");
300 uaccess(rpp, Vfmap, &vfutl);
301 u.u_procp->p_xlink = 0;
302 vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap);
303 u.u_procp->p_flag &= ~SNOVM;
304 rpp->p_ndx = rpp - proc;
305 rpp->p_flag |= SVFDONE;
306 wakeup((caddr_t)rpp);
307 }
308
309 /*
310 * 0 return means parent.
311 */
312 return (0);
313}