1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)kern_fork.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #include "../machine/reg.h"
10: #include "../machine/pte.h"
11: #include "../machine/psl.h"
12:
13: #include "param.h"
14: #include "systm.h"
15: #include "map.h"
16: #include "dir.h"
17: #include "user.h"
18: #include "kernel.h"
19: #include "proc.h"
20: #include "inode.h"
21: #include "seg.h"
22: #include "vm.h"
23: #include "text.h"
24: #include "file.h"
25: #include "acct.h"
26: #include "quota.h"
27:
28: /*
29: * fork system call.
30: */
31: fork()
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:
43: vfork()
44: {
45:
46: fork1(1);
47: }
48:
49: fork1(isvfork)
50: int isvfork;
51: {
52: register struct proc *p1, *p2;
53: register a;
54:
55: a = 0;
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)
62: a++;
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: */
70: p2 = freeproc;
71: if (p2==NULL)
72: tablefull("proc");
73: if (p2==NULL || (u.u_uid!=0 && (p2->p_nxt == NULL || a>MAXUPRC))) {
74: u.u_error = EAGAIN;
75: if (!isvfork) {
76: (void) vsexpand((size_t)0, &u.u_cdmap, 1);
77: (void) vsexpand((size_t)0, &u.u_csmap, 1);
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 */
85: u.u_start = time;
86: u.u_acflag = AFORK;
87: return;
88: }
89: u.u_r.r_val1 = p2->p_pid;
90:
91: out:
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: */
100: newproc(isvfork)
101: int isvfork;
102: {
103: register struct proc *rpp, *rip;
104: register int n;
105: register struct file *fp;
106: static int pidchecked = 0;
107:
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: */
114: mpid++;
115: retry:
116: if (mpid >= 30000) {
117: mpid = 100;
118: pidchecked = 0;
119: }
120: if (mpid >= pidchecked) {
121: int doingzomb = 0;
122:
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;
130: again:
131: for (; rpp != NULL; rpp = rpp->p_nxt) {
132: if (rpp->p_pid == mpid || rpp->p_pgrp == mpid) {
133: mpid++;
134: if (mpid >= pidchecked)
135: goto retry;
136: }
137: if (rpp->p_pid > mpid && pidchecked > rpp->p_pid)
138: pidchecked = rpp->p_pid;
139: if (rpp->p_pgrp > mpid && pidchecked > rpp->p_pgrp)
140: pidchecked = rpp->p_pgrp;
141: }
142: if (!doingzomb) {
143: doingzomb = 1;
144: rpp = zombproc;
145: goto again;
146: }
147: }
148: if ((rpp = freeproc) == NULL)
149: panic("no procs");
150:
151: freeproc = rpp->p_nxt; /* off freeproc */
152: rpp->p_nxt = allproc; /* onto allproc */
153: rpp->p_nxt->p_prev = &rpp->p_nxt; /* (allproc is never NULL) */
154: rpp->p_prev = &allproc;
155: allproc = rpp;
156:
157: /*
158: * Make a proc table entry for the new process.
159: */
160: rip = u.u_procp;
161: #ifdef QUOTA
162: rpp->p_quota = rip->p_quota;
163: rpp->p_quota->q_cnt++;
164: #endif
165: rpp->p_stat = SIDL;
166: timerclear(&rpp->p_realtimer.it_value);
167: rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SOUSIG));
168: if (isvfork) {
169: rpp->p_flag |= SVFORK;
170: rpp->p_ndx = rip->p_ndx;
171: } else
172: rpp->p_ndx = rpp - proc;
173: rpp->p_uid = rip->p_uid;
174: rpp->p_pgrp = rip->p_pgrp;
175: rpp->p_nice = rip->p_nice;
176: rpp->p_textp = isvfork ? 0 : rip->p_textp;
177: rpp->p_pid = mpid;
178: rpp->p_ppid = rip->p_pid;
179: rpp->p_pptr = rip;
180: rpp->p_osptr = rip->p_cptr;
181: if (rip->p_cptr)
182: rip->p_cptr->p_ysptr = rpp;
183: rpp->p_ysptr = NULL;
184: rpp->p_cptr = NULL;
185: rip->p_cptr = rpp;
186: rpp->p_time = 0;
187: rpp->p_cpu = 0;
188: rpp->p_sigmask = rip->p_sigmask;
189: rpp->p_sigcatch = rip->p_sigcatch;
190: rpp->p_sigignore = rip->p_sigignore;
191: /* take along any pending signals like stops? */
192: if (isvfork) {
193: rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0;
194: rpp->p_szpt = clrnd(ctopt(UPAGES));
195: forkstat.cntvfork++;
196: forkstat.sizvfork += rip->p_dsize + rip->p_ssize;
197: } else {
198: rpp->p_tsize = rip->p_tsize;
199: rpp->p_dsize = rip->p_dsize;
200: rpp->p_ssize = rip->p_ssize;
201: rpp->p_szpt = rip->p_szpt;
202: forkstat.cntfork++;
203: forkstat.sizfork += rip->p_dsize + rip->p_ssize;
204: }
205: rpp->p_rssize = 0;
206: rpp->p_maxrss = rip->p_maxrss;
207: rpp->p_wchan = 0;
208: rpp->p_slptime = 0;
209: rpp->p_pctcpu = 0;
210: rpp->p_cpticks = 0;
211: n = PIDHASH(rpp->p_pid);
212: rpp->p_idhash = pidhash[n];
213: pidhash[n] = rpp - proc;
214: multprog++;
215:
216: /*
217: * Increase reference counts on shared objects.
218: */
219: for (n = 0; n <= u.u_lastfile; n++) {
220: fp = u.u_ofile[n];
221: if (fp == NULL)
222: continue;
223: fp->f_count++;
224: }
225: u.u_cdir->i_count++;
226: if (u.u_rdir)
227: u.u_rdir->i_count++;
228:
229: /*
230: * This begins the section where we must prevent the parent
231: * from being swapped.
232: */
233: rip->p_flag |= SKEEP;
234: if (procdup(rpp, isvfork))
235: return (1);
236:
237: /*
238: * Make child runnable and add to run queue.
239: */
240: (void) splclock();
241: rpp->p_stat = SRUN;
242: setrq(rpp);
243: (void) spl0();
244:
245: /*
246: * Cause child to take a non-local goto as soon as it runs.
247: * On older systems this was done with SSWAP bit in proc
248: * table; on VAX we use u.u_pcb.pcb_sswap so don't need
249: * to do rpp->p_flag |= SSWAP. Actually do nothing here.
250: */
251: /* rpp->p_flag |= SSWAP; */
252:
253: /*
254: * Now can be swapped.
255: */
256: rip->p_flag &= ~SKEEP;
257:
258: /*
259: * If vfork make chain from parent process to child
260: * (where virtal memory is temporarily). Wait for
261: * child to finish, steal virtual memory back,
262: * and wakeup child to let it die.
263: */
264: if (isvfork) {
265: u.u_procp->p_xlink = rpp;
266: u.u_procp->p_flag |= SNOVM;
267: while (rpp->p_flag & SVFORK)
268: sleep((caddr_t)rpp, PZERO - 1);
269: if ((rpp->p_flag & SLOAD) == 0)
270: panic("newproc vfork");
271: uaccess(rpp, Vfmap, &vfutl);
272: u.u_procp->p_xlink = 0;
273: vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap);
274: u.u_procp->p_flag &= ~SNOVM;
275: rpp->p_ndx = rpp - proc;
276: rpp->p_flag |= SVFDONE;
277: wakeup((caddr_t)rpp);
278: }
279:
280: /*
281: * 0 return means parent.
282: */
283: return (0);
284: }
Defined functions
fork
defined in line
31; used 2 times
fork1
defined in line
49; used 2 times
vfork
defined in line
43; used 2 times