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