1 /* kern_fork.c 6.1 83/07/29 */ 2 3 #include "../machine/reg.h" 4 #include "../machine/pte.h" 5 #include "../machine/psl.h" 6 7 #include "../h/param.h" 8 #include "../h/systm.h" 9 #include "../h/map.h" 10 #include "../h/dir.h" 11 #include "../h/user.h" 12 #include "../h/kernel.h" 13 #include "../h/proc.h" 14 #include "../h/inode.h" 15 #include "../h/seg.h" 16 #include "../h/vm.h" 17 #include "../h/text.h" 18 #include "../h/file.h" 19 #include "../h/acct.h" 20 #include "../h/quota.h" 21 22 /* 23 * fork system call. 24 */ 25 fork() 26 { 27 28 u.u_cdmap = zdmap; 29 u.u_csmap = zdmap; 30 if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { 31 u.u_r.r_val2 = 0; 32 return; 33 } 34 fork1(0); 35 } 36 37 vfork() 38 { 39 40 fork1(1); 41 } 42 43 fork1(isvfork) 44 int isvfork; 45 { 46 register struct proc *p1, *p2; 47 register a; 48 49 a = 0; 50 p2 = NULL; 51 for (p1 = proc; p1 < procNPROC; p1++) { 52 if (p1->p_stat==NULL && p2==NULL) 53 p2 = p1; 54 else { 55 if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 56 a++; 57 } 58 } 59 /* 60 * Disallow if 61 * No processes at all; 62 * not su and too many procs owned; or 63 * not su and would take last slot. 64 */ 65 if (p2==NULL) 66 tablefull("proc"); 67 if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { 68 u.u_error = EAGAIN; 69 if (!isvfork) { 70 (void) vsexpand(0, &u.u_cdmap, 1); 71 (void) vsexpand(0, &u.u_csmap, 1); 72 } 73 goto out; 74 } 75 p1 = u.u_procp; 76 if (newproc(isvfork)) { 77 u.u_r.r_val1 = p1->p_pid; 78 u.u_r.r_val2 = 1; /* child */ 79 u.u_start = time.tv_sec; 80 u.u_acflag = AFORK; 81 return; 82 } 83 u.u_r.r_val1 = p2->p_pid; 84 85 out: 86 u.u_r.r_val2 = 0; 87 } 88 89 /* 90 * Create a new process-- the internal version of 91 * sys fork. 92 * It returns 1 in the new process, 0 in the old. 93 */ 94 newproc(isvfork) 95 int isvfork; 96 { 97 register struct proc *p; 98 register struct proc *rpp, *rip; 99 register int n; 100 register struct file *fp; 101 102 p = NULL; 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 retry: 110 mpid++; 111 if (mpid >= 30000) { 112 mpid = 0; 113 goto retry; 114 } 115 for (rpp = proc; rpp < procNPROC; rpp++) { 116 if (rpp->p_stat == NULL && p==NULL) 117 p = rpp; 118 if (rpp->p_pid==mpid || rpp->p_pgrp==mpid) 119 goto retry; 120 } 121 if ((rpp = p) == NULL) 122 panic("no procs"); 123 124 /* 125 * Make a proc table entry for the new process. 126 */ 127 rip = u.u_procp; 128 #ifdef QUOTA 129 rpp->p_quota = rip->p_quota; 130 rpp->p_quota->q_cnt++; 131 #endif 132 rpp->p_stat = SIDL; 133 timerclear(&rpp->p_realtimer.it_value); 134 rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SOUSIG)); 135 if (isvfork) { 136 rpp->p_flag |= SVFORK; 137 rpp->p_ndx = rip->p_ndx; 138 } else 139 rpp->p_ndx = rpp - proc; 140 rpp->p_uid = rip->p_uid; 141 rpp->p_pgrp = rip->p_pgrp; 142 rpp->p_nice = rip->p_nice; 143 rpp->p_textp = isvfork ? 0 : rip->p_textp; 144 rpp->p_pid = mpid; 145 rpp->p_ppid = rip->p_pid; 146 rpp->p_pptr = rip; 147 rpp->p_osptr = rip->p_cptr; 148 if (rip->p_cptr) 149 rip->p_cptr->p_ysptr = rpp; 150 rpp->p_ysptr = NULL; 151 rpp->p_cptr = NULL; 152 rip->p_cptr = rpp; 153 rpp->p_time = 0; 154 rpp->p_cpu = 0; 155 rpp->p_sigmask = rip->p_sigmask; 156 rpp->p_sigcatch = rip->p_sigcatch; 157 rpp->p_sigignore = rip->p_sigignore; 158 /* take along any pending signals like stops? */ 159 if (isvfork) { 160 rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0; 161 rpp->p_szpt = clrnd(ctopt(UPAGES)); 162 forkstat.cntvfork++; 163 forkstat.sizvfork += rip->p_dsize + rip->p_ssize; 164 } else { 165 rpp->p_tsize = rip->p_tsize; 166 rpp->p_dsize = rip->p_dsize; 167 rpp->p_ssize = rip->p_ssize; 168 rpp->p_szpt = rip->p_szpt; 169 forkstat.cntfork++; 170 forkstat.sizfork += rip->p_dsize + rip->p_ssize; 171 } 172 rpp->p_rssize = 0; 173 rpp->p_maxrss = rip->p_maxrss; 174 rpp->p_wchan = 0; 175 rpp->p_slptime = 0; 176 rpp->p_pctcpu = 0; 177 rpp->p_cpticks = 0; 178 n = PIDHASH(rpp->p_pid); 179 p->p_idhash = pidhash[n]; 180 pidhash[n] = rpp - proc; 181 multprog++; 182 183 /* 184 * Increase reference counts on shared objects. 185 */ 186 for (n = 0; n < NOFILE; n++) { 187 fp = u.u_ofile[n]; 188 if (fp == NULL) 189 continue; 190 fp->f_count++; 191 } 192 u.u_cdir->i_count++; 193 if (u.u_rdir) 194 u.u_rdir->i_count++; 195 196 /* 197 * Partially simulate the environment 198 * of the new process so that when it is actually 199 * created (by copying) it will look right. 200 * This begins the section where we must prevent the parent 201 * from being swapped. 202 */ 203 rip->p_flag |= SKEEP; 204 if (procdup(rpp, isvfork)) 205 return (1); 206 207 /* 208 * Make child runnable and add to run queue. 209 */ 210 (void) spl6(); 211 rpp->p_stat = SRUN; 212 setrq(rpp); 213 (void) spl0(); 214 215 /* 216 * Cause child to take a non-local goto as soon as it runs. 217 * On older systems this was done with SSWAP bit in proc 218 * table; on VAX we use u.u_pcb.pcb_sswap so don't need 219 * to do rpp->p_flag |= SSWAP. Actually do nothing here. 220 */ 221 /* rpp->p_flag |= SSWAP; */ 222 223 /* 224 * Now can be swapped. 225 */ 226 rip->p_flag &= ~SKEEP; 227 228 /* 229 * If vfork make chain from parent process to child 230 * (where virtal memory is temporarily). Wait for 231 * child to finish, steal virtual memory back, 232 * and wakeup child to let it die. 233 */ 234 if (isvfork) { 235 u.u_procp->p_xlink = rpp; 236 u.u_procp->p_flag |= SNOVM; 237 while (rpp->p_flag & SVFORK) 238 sleep((caddr_t)rpp, PZERO - 1); 239 if ((rpp->p_flag & SLOAD) == 0) 240 panic("newproc vfork"); 241 uaccess(rpp, Vfmap, &vfutl); 242 u.u_procp->p_xlink = 0; 243 vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap); 244 u.u_procp->p_flag &= ~SNOVM; 245 rpp->p_ndx = rpp - proc; 246 rpp->p_flag |= SVFDONE; 247 wakeup((caddr_t)rpp); 248 } 249 250 /* 251 * 0 return means parent. 252 */ 253 return (0); 254 } 255