1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kern_fork.c 7.22 (Berkeley) 12/05/90 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "map.h" 13 #include "user.h" 14 #include "kernel.h" 15 #include "proc.h" 16 #include "vnode.h" 17 #include "seg.h" 18 #include "file.h" 19 #include "acct.h" 20 #include "ktrace.h" 21 22 #include "machine/reg.h" 23 #include "machine/psl.h" 24 25 /* 26 * fork system call. 27 */ 28 /* ARGSUSED */ 29 fork(p, uap, retval) 30 struct proc *p; 31 struct args *uap; 32 int retval[]; 33 { 34 int error; 35 36 return (fork1(p, 0, retval)); 37 } 38 39 /* ARGSUSED */ 40 vfork(p, uap, retval) 41 struct proc *p; 42 struct args *uap; 43 int retval[]; 44 { 45 46 return (fork1(p, 1, retval)); 47 } 48 49 fork1(p1, isvfork, retval) 50 register struct proc *p1; 51 int isvfork, retval[]; 52 { 53 register struct proc *p2; 54 register int a; 55 56 a = 0; 57 if (p1->p_uid != 0) { 58 for (p2 = allproc; p2; p2 = p2->p_nxt) 59 if (p2->p_uid == p1->p_uid) 60 a++; 61 for (p2 = zombproc; p2; p2 = p2->p_nxt) 62 if (p2->p_uid == p1->p_uid) 63 a++; 64 } 65 /* 66 * Disallow if 67 * No processes at all; 68 * not su and too many procs owned; or 69 * not su and would take last slot. 70 */ 71 p2 = freeproc; 72 if (p2==NULL) 73 tablefull("proc"); 74 if (p2 == NULL || 75 (p1->p_uid != 0 && (p2->p_nxt == NULL || a > MAXUPRC))) { 76 retval[1] = 0; 77 return (EAGAIN); 78 } 79 if (newproc(isvfork)) { 80 retval[0] = p1->p_pid; 81 retval[1] = 1; /* child */ 82 u.u_acflag = AFORK; 83 return (0); 84 } 85 retval[0] = p2->p_pid; 86 retval[1] = 0; 87 return (0); 88 } 89 90 /* 91 * Create a new process-- the internal version of 92 * sys fork. 93 * It returns 1 in the new process, 0 in the old. 94 */ 95 newproc(isvfork) 96 int isvfork; 97 { 98 register struct proc *rpp, *rip; 99 register int n; 100 register struct file *fp; 101 static int pidchecked = 0; 102 103 /* 104 * First, just locate a slot for a process 105 * and copy the useful info from this process into it. 106 * The panic "cannot happen" because fork has already 107 * checked for the existence of a slot. 108 */ 109 mpid++; 110 retry: 111 if (mpid >= PID_MAX) { 112 mpid = 100; 113 pidchecked = 0; 114 } 115 if (mpid >= pidchecked) { 116 int doingzomb = 0; 117 118 pidchecked = PID_MAX; 119 /* 120 * Scan the proc table to check whether this pid 121 * is in use. Remember the lowest pid that's greater 122 * than mpid, so we can avoid checking for a while. 123 */ 124 rpp = allproc; 125 again: 126 for (; rpp != NULL; rpp = rpp->p_nxt) { 127 if (rpp->p_pid == mpid || rpp->p_pgrp->pg_id == mpid) { 128 mpid++; 129 if (mpid >= pidchecked) 130 goto retry; 131 } 132 if (rpp->p_pid > mpid && pidchecked > rpp->p_pid) 133 pidchecked = rpp->p_pid; 134 if (rpp->p_pgrp->pg_id > mpid && 135 pidchecked > rpp->p_pgrp->pg_id) 136 pidchecked = rpp->p_pgrp->pg_id; 137 } 138 if (!doingzomb) { 139 doingzomb = 1; 140 rpp = zombproc; 141 goto again; 142 } 143 } 144 if ((rpp = freeproc) == NULL) 145 panic("no procs"); 146 147 freeproc = rpp->p_nxt; /* off freeproc */ 148 rpp->p_nxt = allproc; /* onto allproc */ 149 rpp->p_nxt->p_prev = &rpp->p_nxt; /* (allproc is never NULL) */ 150 rpp->p_prev = &allproc; 151 allproc = rpp; 152 153 /* 154 * Make a proc table entry for the new process. 155 */ 156 rip = u.u_procp; 157 #if defined(tahoe) 158 rpp->p_ckey = rip->p_ckey; 159 rpp->p_dkey = 0; 160 #endif 161 rpp->p_stat = SIDL; 162 timerclear(&rpp->p_realtimer.it_value); 163 rpp->p_flag = SLOAD | (rip->p_flag & (SPAGV|SHPUX)); 164 if (rip->p_session->s_ttyvp != NULL && rip->p_flag & SCTTY) 165 rpp->p_flag |= SCTTY; 166 if (isvfork) 167 rpp->p_flag |= SVFORK; 168 rpp->p_ndx = rpp - proc; 169 bcopy(rip->p_comm, rpp->p_comm, MAXCOMLEN+1); 170 bcopy(rip->p_logname, rpp->p_logname, MAXLOGNAME); 171 rpp->p_uid = rip->p_uid; 172 rpp->p_ruid = rip->p_ruid; 173 rpp->p_rgid = rip->p_rgid; 174 rpp->p_pgrp = rip->p_pgrp; 175 rpp->p_pgrpnxt = rip->p_pgrpnxt; 176 rip->p_pgrpnxt = rpp; 177 rpp->p_nice = rip->p_nice; 178 rpp->p_pid = mpid; 179 rpp->p_ppid = rip->p_pid; 180 rpp->p_pptr = rip; 181 rpp->p_osptr = rip->p_cptr; 182 if (rip->p_cptr) 183 rip->p_cptr->p_ysptr = rpp; 184 rpp->p_ysptr = NULL; 185 rpp->p_cptr = NULL; 186 rip->p_cptr = rpp; 187 rpp->p_time = 0; 188 bzero((caddr_t)&rpp->p_utime, sizeof (struct timeval)); 189 bzero((caddr_t)&rpp->p_stime, sizeof (struct timeval)); 190 rpp->p_cpu = 0; 191 rpp->p_sigmask = rip->p_sigmask; 192 rpp->p_sigcatch = rip->p_sigcatch; 193 rpp->p_sigignore = rip->p_sigignore; 194 #ifdef KTRACE 195 if (rip->p_traceflag&KTRFAC_INHERIT) { 196 rpp->p_traceflag = rip->p_traceflag; 197 if ((rpp->p_tracep = rip->p_tracep) != NULL) 198 VREF(rpp->p_tracep); 199 } else { 200 rpp->p_tracep = NULL; 201 rpp->p_traceflag = 0; 202 } 203 #endif 204 rpp->p_rssize = 0; 205 rpp->p_maxrss = rip->p_maxrss; 206 rpp->p_wchan = 0; 207 rpp->p_slptime = 0; 208 rpp->p_pctcpu = 0; 209 rpp->p_cpticks = 0; 210 { 211 struct proc **hash = &pidhash[PIDHASH(rpp->p_pid)]; 212 213 rpp->p_hash = *hash; 214 *hash = rpp; 215 } 216 217 /* 218 * Increase reference counts on shared objects. 219 */ 220 for (n = 0; n <= u.u_lastfile; n++) { 221 fp = u.u_ofile[n]; 222 if (fp == NULL) 223 continue; 224 fp->f_count++; 225 } 226 #ifdef SYSVSHM 227 if (rip->p_shm) 228 shmfork(rip, rpp, isvfork); 229 #endif 230 VREF(u.u_cdir); 231 if (u.u_rdir) 232 VREF(u.u_rdir); 233 crhold(u.u_cred); 234 235 /* 236 * This begins the section where we must prevent the parent 237 * from being swapped. 238 */ 239 rip->p_flag |= SKEEP; 240 if (procdup(rpp, isvfork)) { 241 (void) splclock(); 242 u.u_start = time; 243 (void) spl0(); 244 return (1); 245 } 246 247 /* 248 * Make child runnable and add to run queue. 249 */ 250 (void) splclock(); 251 rpp->p_stat = SRUN; 252 setrq(rpp); 253 (void) spl0(); 254 255 /* 256 * Cause child to take a non-local goto as soon as it runs. 257 * On older systems this was done with SSWAP bit in proc 258 * table; on VAX we use u.u_pcb.pcb_sswap so don't need 259 * to do rpp->p_flag |= SSWAP. Actually do nothing here. 260 */ 261 /* rpp->p_flag |= SSWAP; */ 262 263 /* 264 * Now can be swapped. 265 */ 266 rip->p_flag &= ~SKEEP; 267 268 /* 269 * XXX preserve synchronization semantics of vfork 270 */ 271 if (isvfork) { 272 u.u_procp->p_flag |= SNOVM; 273 while (rpp->p_flag & SVFORK) 274 sleep((caddr_t)rpp, PZERO - 1); 275 if ((rpp->p_flag & SLOAD) == 0) 276 panic("newproc vfork"); 277 u.u_procp->p_flag &= ~SNOVM; 278 rpp->p_flag |= SVFDONE; 279 wakeup((caddr_t)rpp); 280 } 281 282 /* 283 * 0 return means parent. 284 */ 285 return (0); 286 } 287