-
-/*
- * Create a new process-- the internal version of
- * sys fork.
- * It returns 1 in the new process, 0 in the old.
- */
-newproc(isvfork)
- int isvfork;
-{
- register struct proc *p;
- register struct proc *rpp, *rip;
- register int n;
-
- p = NULL;
- /*
- * First, just locate a slot for a process
- * and copy the useful info from this process into it.
- * The panic "cannot happen" because fork has already
- * checked for the existence of a slot.
- */
-retry:
- mpid++;
- if (mpid >= 30000) {
- mpid = 0;
- goto retry;
- }
- for (rpp = proc; rpp < procNPROC; rpp++) {
- if (rpp->p_stat == NULL && p==NULL)
- p = rpp;
- if (rpp->p_pid==mpid || rpp->p_pgrp==mpid)
- goto retry;
- }
- if ((rpp = p) == NULL)
- panic("no procs");
-
- /*
- * Make a proc table entry for the new process.
- */
- rip = u.u_procp;
- rpp->p_stat = SIDL;
- rpp->p_clktim = 0;
- rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SNUSIG));
- if (isvfork) {
- rpp->p_flag |= SVFORK;
- rpp->p_ndx = rip->p_ndx;
- } else
- rpp->p_ndx = rpp - proc;
- rpp->p_uid = rip->p_uid;
- rpp->p_pgrp = rip->p_pgrp;
- rpp->p_nice = rip->p_nice;
- rpp->p_textp = isvfork ? 0 : rip->p_textp;
- rpp->p_pid = mpid;
- rpp->p_ppid = rip->p_pid;
- rpp->p_pptr = rip;
- rpp->p_time = 0;
- rpp->p_cpu = 0;
- rpp->p_siga0 = rip->p_siga0;
- rpp->p_siga1 = rip->p_siga1;
- /* take along any pending signals, like stops? */
- if (isvfork) {
- rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0;
- rpp->p_szpt = clrnd(ctopt(UPAGES));
- forkstat.cntvfork++;
- forkstat.sizvfork += rip->p_dsize + rip->p_ssize;
- } else {
- rpp->p_tsize = rip->p_tsize;
- rpp->p_dsize = rip->p_dsize;
- rpp->p_ssize = rip->p_ssize;
- rpp->p_szpt = rip->p_szpt;
- forkstat.cntfork++;
- forkstat.sizfork += rip->p_dsize + rip->p_ssize;
- }
- rpp->p_rssize = 0;
- rpp->p_maxrss = rip->p_maxrss;
- rpp->p_wchan = 0;
- rpp->p_slptime = 0;
- rpp->p_pctcpu = 0;
- rpp->p_cpticks = 0;
- n = PIDHASH(rpp->p_pid);
- p->p_idhash = pidhash[n];
- pidhash[n] = rpp - proc;
- multprog++;
-
- /*
- * Increase reference counts on shared objects.
- */
- for(n=0; n<NOFILE; n++)
- if (u.u_ofile[n] != NULL)
- u.u_ofile[n]->f_count++;
- u.u_cdir->i_count++;
- if (u.u_rdir)
- u.u_rdir->i_count++;
-
- /*
- * Partially simulate the environment
- * of the new process so that when it is actually
- * created (by copying) it will look right.
- * This begins the section where we must prevent the parent
- * from being swapped.
- */
- rip->p_flag |= SKEEP;
- if (procdup(rpp, isvfork))
- return (1);
-
- /*
- * Make child runnable and add to run queue.
- */
- (void) spl6();
- rpp->p_stat = SRUN;
- setrq(rpp);
- (void) spl0();
-
- /*
- * Cause child to take a non-local goto as soon as it runs.
- * On older systems this was done with SSWAP bit in proc
- * table; on VAX we use u.u_pcb.pcb_sswap so don't need
- * to do rpp->p_flag |= SSWAP. Actually do nothing here.
- */
- /* rpp->p_flag |= SSWAP; */
-
- /*
- * Now can be swapped.
- */
- rip->p_flag &= ~SKEEP;
-
- /*
- * If vfork make chain from parent process to child
- * (where virtal memory is temporarily). Wait for
- * child to finish, steal virtual memory back,
- * and wakeup child to let it die.
- */
- if (isvfork) {
- u.u_procp->p_xlink = rpp;
- u.u_procp->p_flag |= SNOVM;
- while (rpp->p_flag & SVFORK)
- sleep((caddr_t)rpp, PZERO - 1);
- if ((rpp->p_flag & SLOAD) == 0)
- panic("newproc vfork");
- uaccess(rpp, Vfmap, &vfutl);
- u.u_procp->p_xlink = 0;
- vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap);
- u.u_procp->p_flag &= ~SNOVM;
- rpp->p_ndx = rpp - proc;
- rpp->p_flag |= SVFDONE;
- wakeup((caddr_t)rpp);
- }
-
- /*
- * 0 return means parent.
- */
- return (0);
-}