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