1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 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 * 17 * @(#)kern_fork.c 7.17 (Berkeley) 06/05/90 18 */ 19 20 #include "param.h" 21 #include "systm.h" 22 #include "map.h" 23 #include "syscontext.h" 24 #include "kernel.h" 25 #include "proc.h" 26 #include "vnode.h" 27 #include "seg.h" 28 #include "vm.h" 29 #include "text.h" 30 #include "file.h" 31 #include "acct.h" 32 #include "ktrace.h" 33 #include "../ufs/quota.h" 34 35 #include "machine/reg.h" 36 #include "machine/pte.h" 37 #include "machine/psl.h" 38 39 /* 40 * fork system call. 41 */ 42 /* ARGSUSED */ 43 fork(p, uap, retval) 44 struct proc *p; 45 struct args *uap; 46 int retval[]; 47 { 48 int error; 49 50 u.u_cdmap = zdmap; 51 u.u_csmap = zdmap; 52 if (error = swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap)) { 53 retval[1] = 0; 54 RETURN (error); 55 } 56 RETURN (fork1(p, 0, retval)); 57 } 58 59 /* ARGSUSED */ 60 vfork(p, uap, retval) 61 struct proc *p; 62 struct args *uap; 63 int retval[]; 64 { 65 66 RETURN (fork1(p, 1, retval)); 67 } 68 69 fork1(p1, isvfork, retval) 70 register struct proc *p1; 71 int isvfork, retval[]; 72 { 73 register struct proc *p2; 74 register int a; 75 76 a = 0; 77 if (p1->p_uid != 0) { 78 for (p2 = allproc; p2; p2 = p2->p_nxt) 79 if (p2->p_uid == p1->p_uid) 80 a++; 81 for (p2 = zombproc; p2; p2 = p2->p_nxt) 82 if (p2->p_uid == p1->p_uid) 83 a++; 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 */ 91 p2 = freeproc; 92 if (p2==NULL) 93 tablefull("proc"); 94 if (p2 == NULL || 95 (p1->p_uid != 0 && (p2->p_nxt == NULL || a > MAXUPRC))) { 96 if (!isvfork) { 97 (void) vsexpand((segsz_t)0, &u.u_cdmap, 1); 98 (void) vsexpand((segsz_t)0, &u.u_csmap, 1); 99 } 100 retval[1] = 0; 101 return (EAGAIN); 102 } 103 if (newproc(isvfork)) { 104 retval[0] = p1->p_pid; 105 retval[1] = 1; /* child */ 106 u.u_acflag = AFORK; 107 return (0); 108 } 109 retval[0] = p2->p_pid; 110 retval[1] = 0; 111 return (0); 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 */ 119 newproc(isvfork) 120 int isvfork; 121 { 122 register struct proc *rpp, *rip; 123 register int n; 124 register struct file *fp; 125 static int pidchecked = 0; 126 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 */ 133 mpid++; 134 retry: 135 if (mpid >= 30000) { 136 mpid = 100; 137 pidchecked = 0; 138 } 139 if (mpid >= pidchecked) { 140 int doingzomb = 0; 141 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; 149 again: 150 for (; rpp != NULL; rpp = rpp->p_nxt) { 151 if (rpp->p_pid == mpid || rpp->p_pgrp->pg_id == mpid) { 152 mpid++; 153 if (mpid >= pidchecked) 154 goto retry; 155 } 156 if (rpp->p_pid > mpid && pidchecked > rpp->p_pid) 157 pidchecked = rpp->p_pid; 158 if (rpp->p_pgrp->pg_id > mpid && 159 pidchecked > rpp->p_pgrp->pg_id) 160 pidchecked = rpp->p_pgrp->pg_id; 161 } 162 if (!doingzomb) { 163 doingzomb = 1; 164 rpp = zombproc; 165 goto again; 166 } 167 } 168 if ((rpp = freeproc) == NULL) 169 panic("no procs"); 170 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 177 /* 178 * Make a proc table entry for the new process. 179 */ 180 rip = u.u_procp; 181 #if defined(tahoe) 182 rpp->p_ckey = rip->p_ckey; 183 rpp->p_dkey = 0; 184 #endif 185 rpp->p_stat = SIDL; 186 timerclear(&rpp->p_realtimer.it_value); 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; 190 if (isvfork) { 191 rpp->p_flag |= SVFORK; 192 rpp->p_ndx = rip->p_ndx; 193 } else 194 rpp->p_ndx = rpp - proc; 195 bcopy(rip->p_comm, rpp->p_comm, MAXCOMLEN+1); 196 bcopy(rip->p_logname, rpp->p_logname, MAXLOGNAME); 197 rpp->p_uid = rip->p_uid; 198 rpp->p_ruid = rip->p_ruid; 199 rpp->p_rgid = rip->p_rgid; 200 rpp->p_pgrp = rip->p_pgrp; 201 rpp->p_pgrpnxt = rip->p_pgrpnxt; 202 rip->p_pgrpnxt = rpp; 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; 215 bzero((caddr_t)&rpp->p_utime, sizeof (struct timeval)); 216 bzero((caddr_t)&rpp->p_stime, sizeof (struct timeval)); 217 rpp->p_cpu = 0; 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? */ 222 if (isvfork) { 223 rpp->p_tsize = rpp->p_dsize = rpp->p_mmsize = rpp->p_ssize = 0; 224 rpp->p_szpt = clrnd(ctopt(HIGHPAGES)); 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; 230 rpp->p_mmsize = rip->p_mmsize; 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 } 236 #ifdef KTRACE 237 if (rip->p_traceflag&KTRFAC_INHERIT) { 238 rpp->p_traceflag = rip->p_traceflag; 239 if ((rpp->p_tracep = rip->p_tracep) != NULL) 240 VREF(rpp->p_tracep); 241 } else { 242 rpp->p_tracep = NULL; 243 rpp->p_traceflag = 0; 244 } 245 #endif 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; 252 { 253 struct proc **hash = &pidhash[PIDHASH(rpp->p_pid)]; 254 255 rpp->p_hash = *hash; 256 *hash = rpp; 257 } 258 multprog++; 259 260 /* 261 * Increase reference counts on shared objects. 262 */ 263 for (n = 0; n <= u.u_lastfile; n++) { 264 fp = u.u_ofile[n]; 265 if (fp == NULL) 266 continue; 267 fp->f_count++; 268 } 269 VREF(u.u_cdir); 270 if (u.u_rdir) 271 VREF(u.u_rdir); 272 crhold(u.u_cred); 273 274 /* 275 * This begins the section where we must prevent the parent 276 * from being swapped. 277 */ 278 rip->p_flag |= SKEEP; 279 if (procdup(rpp, isvfork)) { 280 (void) splclock(); 281 u.u_start = time; 282 (void) spl0(); 283 return (1); 284 } 285 286 /* 287 * Make child runnable and add to run queue. 288 */ 289 (void) splclock(); 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 } 334