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