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.3 (Berkeley) 10/18/88 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->pg_id == 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->pg_id > mpid && 140 pidchecked > rpp->p_pgrp->pg_id) 141 pidchecked = rpp->p_pgrp->pg_id; 142 } 143 if (!doingzomb) { 144 doingzomb = 1; 145 rpp = zombproc; 146 goto again; 147 } 148 } 149 if ((rpp = freeproc) == NULL) 150 panic("no procs"); 151 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 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++; 165 #endif 166 #if defined(tahoe) 167 rpp->p_ckey = rip->p_ckey; 168 rpp->p_dkey = 0; 169 #endif 170 rpp->p_stat = SIDL; 171 timerclear(&rpp->p_realtimer.it_value); 172 rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SOUSIG)); 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; 180 rpp->p_pgrpnxt = rip->p_pgrpnxt; 181 rip->p_pgrpnxt = rpp; 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; 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? */ 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 } 212 rpp->p_rssize = 0; 213 rpp->p_maxrss = rip->p_maxrss; 214 rpp->p_wchan = 0; 215 rpp->p_slptime = 0; 216 rpp->p_pctcpu = 0; 217 rpp->p_cpticks = 0; 218 n = PIDHASH(rpp->p_pid); 219 rpp->p_idhash = pidhash[n]; 220 pidhash[n] = rpp - proc; 221 multprog++; 222 223 /* 224 * Increase reference counts on shared objects. 225 */ 226 for (n = 0; n <= u.u_lastfile; n++) { 227 fp = u.u_ofile[n]; 228 if (fp == NULL) 229 continue; 230 fp->f_count++; 231 } 232 u.u_cdir->i_count++; 233 if (u.u_rdir) 234 u.u_rdir->i_count++; 235 236 /* 237 * This begins the section where we must prevent the parent 238 * from being swapped. 239 */ 240 rip->p_flag |= SKEEP; 241 if (procdup(rpp, isvfork)) 242 return (1); 243 244 /* 245 * Make child runnable and add to run queue. 246 */ 247 (void) splclock(); 248 rpp->p_stat = SRUN; 249 setrq(rpp); 250 (void) spl0(); 251 252 /* 253 * Cause child to take a non-local goto as soon as it runs. 254 * On older systems this was done with SSWAP bit in proc 255 * table; on VAX we use u.u_pcb.pcb_sswap so don't need 256 * to do rpp->p_flag |= SSWAP. Actually do nothing here. 257 */ 258 /* rpp->p_flag |= SSWAP; */ 259 260 /* 261 * Now can be swapped. 262 */ 263 rip->p_flag &= ~SKEEP; 264 265 /* 266 * If vfork make chain from parent process to child 267 * (where virtal memory is temporarily). Wait for 268 * child to finish, steal virtual memory back, 269 * and wakeup child to let it die. 270 */ 271 if (isvfork) { 272 u.u_procp->p_xlink = rpp; 273 u.u_procp->p_flag |= SNOVM; 274 while (rpp->p_flag & SVFORK) 275 sleep((caddr_t)rpp, PZERO - 1); 276 if ((rpp->p_flag & SLOAD) == 0) 277 panic("newproc vfork"); 278 uaccess(rpp, Vfmap, &vfutl); 279 u.u_procp->p_xlink = 0; 280 vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap); 281 u.u_procp->p_flag &= ~SNOVM; 282 rpp->p_ndx = rpp - proc; 283 rpp->p_flag |= SVFDONE; 284 wakeup((caddr_t)rpp); 285 } 286 287 /* 288 * 0 return means parent. 289 */ 290 return (0); 291 } 292