add POSIX-style byte-level record locking
[unix-history] / usr / src / sys / kern / kern_fork.c
index d32f74f..b783420 100644 (file)
@@ -1,58 +1,66 @@
-/*     kern_fork.c     6.5     84/08/29        */
-
-#include "../machine/reg.h"
-#include "../machine/pte.h"
-#include "../machine/psl.h"
+/*
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)kern_fork.c 7.23 (Berkeley) %G%
+ */
 
 #include "param.h"
 #include "systm.h"
 #include "map.h"
 
 #include "param.h"
 #include "systm.h"
 #include "map.h"
-#include "dir.h"
 #include "user.h"
 #include "user.h"
+#include "filedesc.h"
 #include "kernel.h"
 #include "proc.h"
 #include "kernel.h"
 #include "proc.h"
-#include "inode.h"
+#include "vnode.h"
 #include "seg.h"
 #include "seg.h"
-#include "vm.h"
-#include "text.h"
 #include "file.h"
 #include "acct.h"
 #include "file.h"
 #include "acct.h"
-#include "quota.h"
+#include "ktrace.h"
+
+#include "machine/reg.h"
+#include "machine/psl.h"
 
 /*
  * fork system call.
  */
 
 /*
  * fork system call.
  */
-fork()
+/* ARGSUSED */
+fork(p, uap, retval)
+       struct proc *p;
+       struct args *uap;
+       int retval[];
 {
 {
+       int error;
 
 
-       u.u_cdmap = zdmap;
-       u.u_csmap = zdmap;
-       if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) {
-               u.u_r.r_val2 = 0;
-               return;
-       }
-       fork1(0);
+       return (fork1(p, 0, retval));
 }
 
 }
 
-vfork()
+/* ARGSUSED */
+vfork(p, uap, retval)
+       struct proc *p;
+       struct args *uap;
+       int retval[];
 {
 
 {
 
-       fork1(1);
+       return (fork1(p, 1, retval));
 }
 
 }
 
-fork1(isvfork)
-       int isvfork;
+fork1(p1, isvfork, retval)
+       register struct proc *p1;
+       int isvfork, retval[];
 {
 {
-       register struct proc *p1, *p2;
-       register a;
+       register struct proc *p2;
+       register int a;
 
        a = 0;
 
        a = 0;
-       if (u.u_uid != 0) {
-               for (p1 = allproc; p1; p1 = p1->p_nxt)
-                       if (p1->p_uid == u.u_uid)
+       if (p1->p_uid != 0) {
+               for (p2 = allproc; p2; p2 = p2->p_nxt)
+                       if (p2->p_uid == p1->p_uid)
                                a++;
                                a++;
-               for (p1 = zombproc; p1; p1 = p1->p_nxt)
-                       if (p1->p_uid == u.u_uid)
+               for (p2 = zombproc; p2; p2 = p2->p_nxt)
+                       if (p2->p_uid == p1->p_uid)
                                a++;
        }
        /*
                                a++;
        }
        /*
@@ -64,26 +72,20 @@ fork1(isvfork)
        p2 = freeproc;
        if (p2==NULL)
                tablefull("proc");
        p2 = freeproc;
        if (p2==NULL)
                tablefull("proc");
-       if (p2==NULL || (u.u_uid!=0 && (p2->p_nxt == NULL || a>MAXUPRC))) {
-               u.u_error = EAGAIN;
-               if (!isvfork) {
-                       (void) vsexpand(0, &u.u_cdmap, 1);
-                       (void) vsexpand(0, &u.u_csmap, 1);
-               }
-               goto out;
+       if (p2 == NULL ||
+           (p1->p_uid != 0 && (p2->p_nxt == NULL || a > MAXUPRC))) {
+               retval[1] = 0;
+               return (EAGAIN);
        }
        }
-       p1 = u.u_procp;
        if (newproc(isvfork)) {
        if (newproc(isvfork)) {
-               u.u_r.r_val1 = p1->p_pid;
-               u.u_r.r_val2 = 1;  /* child */
-               u.u_start = time;
+               retval[0] = p1->p_pid;
+               retval[1] = 1;  /* child */
                u.u_acflag = AFORK;
                u.u_acflag = AFORK;
-               return;
+               return (0);
        }
        }
-       u.u_r.r_val1 = p2->p_pid;
-
-out:
-       u.u_r.r_val2 = 0;
+       retval[0] = p2->p_pid;
+       retval[1] = 0;
+       return (0);
 }
 
 /*
 }
 
 /*
@@ -95,7 +97,6 @@ newproc(isvfork)
        int isvfork;
 {
        register struct proc *rpp, *rip;
        int isvfork;
 {
        register struct proc *rpp, *rip;
-       register int n;
        register struct file *fp;
        static int pidchecked = 0;
 
        register struct file *fp;
        static int pidchecked = 0;
 
@@ -107,14 +108,14 @@ newproc(isvfork)
         */
        mpid++;
 retry:
         */
        mpid++;
 retry:
-       if (mpid >= 30000) {
+       if (mpid >= PID_MAX) {
                mpid = 100;
                pidchecked = 0;
        }
        if (mpid >= pidchecked) {
                int doingzomb = 0;
 
                mpid = 100;
                pidchecked = 0;
        }
        if (mpid >= pidchecked) {
                int doingzomb = 0;
 
-               pidchecked = 30000;
+               pidchecked = PID_MAX;
                /*
                 * Scan the proc table to check whether this pid
                 * is in use.  Remember the lowest pid that's greater
                /*
                 * Scan the proc table to check whether this pid
                 * is in use.  Remember the lowest pid that's greater
@@ -123,15 +124,16 @@ retry:
                rpp = allproc;
 again:
                for (; rpp != NULL; rpp = rpp->p_nxt) {
                rpp = allproc;
 again:
                for (; rpp != NULL; rpp = rpp->p_nxt) {
-                       if (rpp->p_pid == mpid || rpp->p_pgrp == mpid) {
+                       if (rpp->p_pid == mpid || rpp->p_pgrp->pg_id == mpid) {
                                mpid++;
                                if (mpid >= pidchecked)
                                        goto retry;
                        }
                        if (rpp->p_pid > mpid && pidchecked > rpp->p_pid)
                                pidchecked = rpp->p_pid;
                                mpid++;
                                if (mpid >= pidchecked)
                                        goto retry;
                        }
                        if (rpp->p_pid > mpid && pidchecked > rpp->p_pid)
                                pidchecked = rpp->p_pid;
-                       if (rpp->p_pgrp > mpid && pidchecked > rpp->p_pgrp)
-                               pidchecked = rpp->p_pgrp;
+                       if (rpp->p_pgrp->pg_id > mpid && 
+                           pidchecked > rpp->p_pgrp->pg_id)
+                               pidchecked = rpp->p_pgrp->pg_id;
                }
                if (!doingzomb) {
                        doingzomb = 1;
                }
                if (!doingzomb) {
                        doingzomb = 1;
@@ -152,22 +154,27 @@ again:
         * Make a proc table entry for the new process.
         */
        rip = u.u_procp;
         * Make a proc table entry for the new process.
         */
        rip = u.u_procp;
-#ifdef QUOTA
-       rpp->p_quota = rip->p_quota;
-       rpp->p_quota->q_cnt++;
+#if defined(tahoe)
+       rpp->p_ckey = rip->p_ckey;
+       rpp->p_dkey = 0;
 #endif
        rpp->p_stat = SIDL;
        timerclear(&rpp->p_realtimer.it_value);
 #endif
        rpp->p_stat = SIDL;
        timerclear(&rpp->p_realtimer.it_value);
-       rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SOUSIG));
-       if (isvfork) {
+       rpp->p_flag = SLOAD | (rip->p_flag & (SPAGV|SHPUX));
+       if (rip->p_session->s_ttyvp != NULL && rip->p_flag & SCTTY)
+               rpp->p_flag |= SCTTY;
+       if (isvfork)
                rpp->p_flag |= SVFORK;
                rpp->p_flag |= SVFORK;
-               rpp->p_ndx = rip->p_ndx;
-       } else
-               rpp->p_ndx = rpp - proc;
+       rpp->p_ndx = rpp - proc;
+       bcopy(rip->p_comm, rpp->p_comm, MAXCOMLEN+1);
+       bcopy(rip->p_logname, rpp->p_logname, MAXLOGNAME);
        rpp->p_uid = rip->p_uid;
        rpp->p_uid = rip->p_uid;
+       rpp->p_ruid = rip->p_ruid;
+       rpp->p_rgid = rip->p_rgid;
        rpp->p_pgrp = rip->p_pgrp;
        rpp->p_pgrp = rip->p_pgrp;
+       rpp->p_pgrpnxt = rip->p_pgrpnxt;
+       rip->p_pgrpnxt = rpp;
        rpp->p_nice = rip->p_nice;
        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_pid = mpid;
        rpp->p_ppid = rip->p_pid;
        rpp->p_pptr = rip;
@@ -178,60 +185,61 @@ again:
        rpp->p_cptr = NULL;
        rip->p_cptr = rpp;
        rpp->p_time = 0;
        rpp->p_cptr = NULL;
        rip->p_cptr = rpp;
        rpp->p_time = 0;
+       bzero((caddr_t)&rpp->p_utime, sizeof (struct timeval));
+       bzero((caddr_t)&rpp->p_stime, sizeof (struct timeval));
        rpp->p_cpu = 0;
        rpp->p_sigmask = rip->p_sigmask;
        rpp->p_sigcatch = rip->p_sigcatch;
        rpp->p_sigignore = rip->p_sigignore;
        rpp->p_cpu = 0;
        rpp->p_sigmask = rip->p_sigmask;
        rpp->p_sigcatch = rip->p_sigcatch;
        rpp->p_sigignore = rip->p_sigignore;
-       /* 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;
+#ifdef KTRACE
+       if (rip->p_traceflag&KTRFAC_INHERIT) {
+               rpp->p_traceflag = rip->p_traceflag;
+               if ((rpp->p_tracep = rip->p_tracep) != NULL)
+                       VREF(rpp->p_tracep);
        } else {
        } 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_tracep = NULL;
+               rpp->p_traceflag = 0;
        }
        }
+#endif
        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;
        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);
-       rpp->p_idhash = pidhash[n];
-       pidhash[n] = rpp - proc;
-       multprog++;
+       {
+       struct proc **hash = &pidhash[PIDHASH(rpp->p_pid)];
+
+       rpp->p_hash = *hash;
+       *hash = rpp;
+       }
 
        /*
         * Increase reference counts on shared objects.
         */
 
        /*
         * Increase reference counts on shared objects.
         */
-       for (n = 0; n < NOFILE; n++) {
-               fp = u.u_ofile[n];
-               if (fp == NULL)
-                       continue;
-               fp->f_count++;
-       }
-       u.u_cdir->i_count++;
-       if (u.u_rdir)
-               u.u_rdir->i_count++;
+       rpp->p_fd = fddup(rip->p_fd, 0);
+#ifdef SYSVSHM
+       if (rip->p_shm)
+               shmfork(rip, rpp, isvfork);
+#endif
+       crhold(u.u_cred);
 
        /*
         * This begins the section where we must prevent the parent
         * from being swapped.
         */
        rip->p_flag |= SKEEP;
 
        /*
         * This begins the section where we must prevent the parent
         * from being swapped.
         */
        rip->p_flag |= SKEEP;
-       if (procdup(rpp, isvfork))
+       if (procdup(rpp, isvfork)) {
+               (void) splclock();
+               u.u_start = time;
+               (void) spl0();
                return (1);
                return (1);
+       }
 
        /*
         * Make child runnable and add to run queue.
         */
 
        /*
         * Make child runnable and add to run queue.
         */
-       (void) spl6();
+       (void) splclock();
        rpp->p_stat = SRUN;
        setrq(rpp);
        (void) spl0();
        rpp->p_stat = SRUN;
        setrq(rpp);
        (void) spl0();
@@ -250,23 +258,15 @@ again:
        rip->p_flag &= ~SKEEP;
 
        /*
        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.
+        * XXX preserve synchronization semantics of vfork
         */
        if (isvfork) {
         */
        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");
                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;
                u.u_procp->p_flag &= ~SNOVM;
-               rpp->p_ndx = rpp - proc;
                rpp->p_flag |= SVFDONE;
                wakeup((caddr_t)rpp);
        }
                rpp->p_flag |= SVFDONE;
                wakeup((caddr_t)rpp);
        }