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
newproc defined in line 100; used 3 times
vfork defined in line 43; used 2 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 934
Valid CSS Valid XHTML 1.0 Strict