BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / kern / kern_fork.c
index 1762c57..e7d1745 100644 (file)
@@ -1,10 +1,36 @@
 /*
 /*
- * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
  * All rights reserved.
  *
  * All rights reserved.
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)kern_fork.c 7.25 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)kern_fork.c 7.29 (Berkeley) 5/15/91
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -24,7 +50,7 @@
 /* ARGSUSED */
 fork(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 fork(p, uap, retval)
        struct proc *p;
-       struct args *uap;
+       void *uap;
        int retval[];
 {
 
        int retval[];
 {
 
@@ -34,7 +60,7 @@ fork(p, uap, retval)
 /* ARGSUSED */
 vfork(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 vfork(p, uap, retval)
        struct proc *p;
-       struct args *uap;
+       void *uap;
        int retval[];
 {
 
        int retval[];
 {
 
@@ -69,7 +95,6 @@ fork1(p1, isvfork, retval)
         * nprocs is the current number of processes,
         * maxproc is the limit.
         */
         * nprocs is the current number of processes,
         * maxproc is the limit.
         */
-       retval[1] = 0;
        if (nprocs >= maxproc || uid == 0 && nprocs >= maxproc + 1) {
                tablefull("proc");
                return (EAGAIN);
        if (nprocs >= maxproc || uid == 0 && nprocs >= maxproc + 1) {
                tablefull("proc");
                return (EAGAIN);
@@ -147,18 +172,23 @@ again:
            (unsigned) ((caddr_t)&p2->p_endzero - (caddr_t)&p2->p_startzero));
        bcopy(&p1->p_startcopy, &p2->p_startcopy,
            (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy));
            (unsigned) ((caddr_t)&p2->p_endzero - (caddr_t)&p2->p_startzero));
        bcopy(&p1->p_startcopy, &p2->p_startcopy,
            (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy));
+       p2->p_spare[0] = 0;     /* XXX - should be in zero range */
+       p2->p_spare[1] = 0;     /* XXX - should be in zero range */
+       p2->p_spare[2] = 0;     /* XXX - should be in zero range */
+       p2->p_spare[3] = 0;     /* XXX - should be in zero range */
 
        /*
         * Duplicate sub-structures as needed.
         * Increase reference counts on shared objects.
 
        /*
         * Duplicate sub-structures as needed.
         * Increase reference counts on shared objects.
+        * The p_stats and p_sigacts substructs are set in vm_fork.
         */
        MALLOC(p2->p_cred, struct pcred *, sizeof(struct pcred),
            M_SUBPROC, M_WAITOK);
        bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred));
         */
        MALLOC(p2->p_cred, struct pcred *, sizeof(struct pcred),
            M_SUBPROC, M_WAITOK);
        bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred));
+       p2->p_cred->p_refcnt = 1;
        crhold(p1->p_ucred);
 
        p2->p_fd = fdcopy(p1);
        crhold(p1->p_ucred);
 
        p2->p_fd = fdcopy(p1);
-       p2->p_stats = p1->p_stats;              /* XXX move; in u. */
        /*
         * If p_limit is still copy-on-write, bump refcnt,
         * otherwise get a copy that won't be modified.
        /*
         * If p_limit is still copy-on-write, bump refcnt,
         * otherwise get a copy that won't be modified.
@@ -171,9 +201,8 @@ again:
                p2->p_limit = p1->p_limit;
                p2->p_limit->p_refcnt++;
        }
                p2->p_limit = p1->p_limit;
                p2->p_limit->p_refcnt++;
        }
-       p2->p_sigacts = p1->p_sigacts;          /* XXX move; in u. */
 
 
-       p2->p_flag = SLOAD | (p1->p_flag & (SPAGV|SHPUX));
+       p2->p_flag = SLOAD | (p1->p_flag & SHPUX);
        if (p1->p_session->s_ttyvp != NULL && p1->p_flag & SCTTY)
                p2->p_flag |= SCTTY;
        if (isvfork)
        if (p1->p_session->s_ttyvp != NULL && p1->p_flag & SCTTY)
                p2->p_flag |= SCTTY;
        if (isvfork)
@@ -205,7 +234,6 @@ again:
        }
 #endif
 
        }
 #endif
 
-       p2->p_regs = p1->p_regs;                 /* XXX move this */
 #if defined(tahoe)
        p2->p_vmspace->p_ckey = p1->p_vmspace->p_ckey; /* XXX move this */
 #endif
 #if defined(tahoe)
        p2->p_vmspace->p_ckey = p1->p_vmspace->p_ckey; /* XXX move this */
 #endif
@@ -215,16 +243,23 @@ again:
         * from being swapped.
         */
        p1->p_flag |= SKEEP;
         * from being swapped.
         */
        p1->p_flag |= SKEEP;
+       /*
+        * Set return values for child before vm_fork,
+        * so they can be copied to child stack.
+        * We return parent pid, and mark as child in retval[1].
+        * NOTE: the kernel stack may be at a different location in the child
+        * process, and thus addresses of automatic variables (including retval)
+        * may be invalid after vm_fork returns in the child process.
+        */
+       retval[0] = p1->p_pid;
+       retval[1] = 1;
        if (vm_fork(p1, p2, isvfork)) {
                /*
        if (vm_fork(p1, p2, isvfork)) {
                /*
-                * Child process.  Set start time, return parent pid,
-                * and mark as child in retval[1].
+                * Child process.  Set start time and get to work.
                 */
                (void) splclock();
                p2->p_stats->p_start = time;
                (void) spl0();
                 */
                (void) splclock();
                p2->p_stats->p_start = time;
                (void) spl0();
-               retval[0] = p1->p_pid;
-               retval[1] = 1;
                p2->p_acflag = AFORK;
                return (0);
        }
                p2->p_acflag = AFORK;
                return (0);
        }
@@ -243,18 +278,19 @@ again:
        p1->p_flag &= ~SKEEP;
 
        /*
        p1->p_flag &= ~SKEEP;
 
        /*
-        * XXX preserve synchronization semantics of vfork
+        * Preserve synchronization semantics of vfork.
         * If waiting for child to exec or exit, set SPPWAIT
         * on child, and sleep on our proc (in case of exit).
         */
        if (isvfork)
                while (p2->p_flag & SPPWAIT)
         * If waiting for child to exec or exit, set SPPWAIT
         * on child, and sleep on our proc (in case of exit).
         */
        if (isvfork)
                while (p2->p_flag & SPPWAIT)
-                       sleep((caddr_t)p1, PZERO - 1);
+                       tsleep((caddr_t)p1, PWAIT, "ppwait", 0);
 
        /*
 
        /*
-        * Return child pid to parent process.
-        * retval[1] was set above.
+        * Return child pid to parent process,
+        * marking us as parent via retval[1].
         */
        retval[0] = p2->p_pid;
         */
        retval[0] = p2->p_pid;
+       retval[1] = 0;
        return (0);
 }
        return (0);
 }