Cleanup POSIX real-time so the kernel compiles without the P1003_1B
[dragonfly.git] / sys / kern / kern_fork.c
index a904afc..841a377 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)kern_fork.c 8.6 (Berkeley) 4/8/94
  * $FreeBSD: src/sys/kern/kern_fork.c,v 1.72.2.13 2003/06/06 20:21:32 tegge Exp $
- * $DragonFly: src/sys/kern/kern_fork.c,v 1.2 2003/06/17 04:28:41 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_fork.c,v 1.16 2003/11/05 23:26:20 dillon Exp $
  */
 
 #include "opt_ktrace.h"
@@ -81,60 +81,54 @@ struct forklist {
 TAILQ_HEAD(forklist_head, forklist);
 static struct forklist_head fork_list = TAILQ_HEAD_INITIALIZER(fork_list);
 
-#ifndef _SYS_SYSPROTO_H_
-struct fork_args {
-       int     dummy;
-};
-#endif
-
 int forksleep; /* Place for fork1() to sleep on. */
 
 /* ARGSUSED */
 int
-fork(p, uap)
-       struct proc *p;
-       struct fork_args *uap;
+fork(struct fork_args *uap)
 {
-       int error;
+       struct proc *p = curproc;
        struct proc *p2;
+       int error;
 
        error = fork1(p, RFFDG | RFPROC, &p2);
        if (error == 0) {
-               p->p_retval[0] = p2->p_pid;
-               p->p_retval[1] = 0;
+               start_forked_proc(p, p2);
+               uap->sysmsg_fds[0] = p2->p_pid;
+               uap->sysmsg_fds[1] = 0;
        }
        return error;
 }
 
 /* ARGSUSED */
 int
-vfork(p, uap)
-       struct proc *p;
-       struct vfork_args *uap;
+vfork(struct vfork_args *uap)
 {
-       int error;
+       struct proc *p = curproc;
        struct proc *p2;
+       int error;
 
        error = fork1(p, RFFDG | RFPROC | RFPPWAIT | RFMEM, &p2);
        if (error == 0) {
-               p->p_retval[0] = p2->p_pid;
-               p->p_retval[1] = 0;
+               start_forked_proc(p, p2);
+               uap->sysmsg_fds[0] = p2->p_pid;
+               uap->sysmsg_fds[1] = 0;
        }
        return error;
 }
 
 int
-rfork(p, uap)
-       struct proc *p;
-       struct rfork_args *uap;
+rfork(struct rfork_args *uap)
 {
-       int error;
+       struct proc *p = curproc;
        struct proc *p2;
+       int error;
 
        error = fork1(p, uap->flags, &p2);
        if (error == 0) {
-               p->p_retval[0] = p2 ? p2->p_pid : 0;
-               p->p_retval[1] = 0;
+               start_forked_proc(p, p2);
+               uap->sysmsg_fds[0] = p2 ? p2->p_pid : 0;
+               uap->sysmsg_fds[1] = 0;
        }
        return error;
 }
@@ -232,9 +226,9 @@ fork1(p1, flags, procp)
         * exceed the limit. The variable nprocs is the current number of
         * processes, maxproc is the limit.
         */
-       uid = p1->p_cred->p_ruid;
+       uid = p1->p_ucred->cr_ruid;
        if ((nprocs >= maxproc - 10 && uid != 0) || nprocs >= maxproc) {
-               tsleep(&forksleep, PUSER, "fork", hz / 2);
+               tsleep(&forksleep, 0, "fork", hz / 2);
                return (EAGAIN);
        }
        /*
@@ -247,14 +241,14 @@ fork1(p1, flags, procp)
         * Increment the count of procs running with this uid. Don't allow
         * a nonprivileged user to exceed their current limit.
         */
-       ok = chgproccnt(p1->p_cred->p_uidinfo, 1,
+       ok = chgproccnt(p1->p_ucred->cr_ruidinfo, 1,
                (uid != 0) ? p1->p_rlimit[RLIMIT_NPROC].rlim_cur : 0);
        if (!ok) {
                /*
                 * Back out the process count
                 */
                nprocs--;
-               tsleep(&forksleep, PUSER, "fork", hz / 2);
+               tsleep(&forksleep, 0, "fork", hz / 2);
                return (EAGAIN);
        }
 
@@ -274,7 +268,6 @@ fork1(p1, flags, procp)
        }
 
        newproc->p_wakeup = 0;
-
        newproc->p_vmspace = NULL;
 
        /*
@@ -353,19 +346,19 @@ again:
         * Duplicate sub-structures as needed.
         * Increase reference counts on shared objects.
         * The p_stats and p_sigacts substructs are set in vm_fork.
+        *
+        * P_CP_RELEASED indicates that the process is starting out in
+        * the kernel (in the fork trampoline).  The flag will be converted
+        * to P_CURPROC when the new process calls userret() and attempts
+        * to return to userland
         */
-       p2->p_flag = P_INMEM;
+       p2->p_flag = P_INMEM | P_CP_RELEASED;
        if (p1->p_flag & P_PROFIL)
                startprofclock(p2);
-       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);
-       uihold(p1->p_cred->p_uidinfo);
-
-       if (p2->p_prison) {
-               p2->p_prison->pr_ref++;
+       p2->p_ucred = crhold(p1->p_ucred);
+
+       if (p2->p_ucred->cr_prison) {
+               p2->p_ucred->cr_prison->pr_ref++;
                p2->p_flag |= P_JAILED;
        }
 
@@ -436,8 +429,7 @@ again:
                         * Shared file descriptor table, and
                         * different process leaders 
                         */
-                       fdtol = filedesc_to_leader_alloc(p1->p_fdtol,
-                                                        p2);
+                       fdtol = filedesc_to_leader_alloc(p1->p_fdtol, p2);
                }
        }
        p2->p_fdtol = fdtol;
@@ -481,6 +473,7 @@ again:
        p2->p_pptr = pptr;
        LIST_INSERT_HEAD(&pptr->p_children, p2, p_sibling);
        LIST_INIT(&p2->p_children);
+       varsymset_init(&p2->p_varsymset, &p1->p_varsymset);
 
 #ifdef KTRACE
        /*
@@ -513,17 +506,17 @@ again:
        vm_fork(p1, p2, flags);
 
        if (flags == (RFFDG | RFPROC)) {
-               cnt.v_forks++;
-               cnt.v_forkpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize;
+               mycpu->gd_cnt.v_forks++;
+               mycpu->gd_cnt.v_forkpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize;
        } else if (flags == (RFFDG | RFPROC | RFPPWAIT | RFMEM)) {
-               cnt.v_vforks++;
-               cnt.v_vforkpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize;
+               mycpu->gd_cnt.v_vforks++;
+               mycpu->gd_cnt.v_vforkpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize;
        } else if (p1 == &proc0) {
-               cnt.v_kthreads++;
-               cnt.v_kthreadpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize;
+               mycpu->gd_cnt.v_kthreads++;
+               mycpu->gd_cnt.v_kthreadpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize;
        } else {
-               cnt.v_rforks++;
-               cnt.v_rforkpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize;
+               mycpu->gd_cnt.v_rforks++;
+               mycpu->gd_cnt.v_rforkpages += p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize;
        }
 
        /*
@@ -540,29 +533,12 @@ again:
         */
        microtime(&(p2->p_stats->p_start));
        p2->p_acflag = AFORK;
-       (void) splhigh();
-       p2->p_stat = SRUN;
-       setrunqueue(p2);
-       (void) spl0();
-
-       /*
-        * Now can be swapped.
-        */
-       PRELE(p1);
 
        /*
         * tell any interested parties about the new process
         */
        KNOTE(&p1->p_klist, NOTE_FORK | p2->p_pid);
 
-       /*
-        * Preserve synchronization semantics of vfork.  If waiting for
-        * child to exec or exit, set P_PPWAIT on child, and sleep on our
-        * proc (in case of exit).
-        */
-       while (p2->p_flag & P_PPWAIT)
-               tsleep(p1, PWAIT, "ppwait", 0);
-
        /*
         * Return child proc pointer to parent.
         */
@@ -620,3 +596,38 @@ rm_at_fork(function)
        }       
        return (0);
 }
+
+/*
+ * Add a forked process to the run queue after any remaining setup, such
+ * as setting the fork handler, has been completed.
+ */
+
+void
+start_forked_proc(struct proc *p1, struct proc *p2)
+{
+       /*
+        * Move from SIDL to RUN queue, and activate the process's thread.
+        * Activation of the thread effectively makes the process "a"
+        * current process, so we do not setrunqueue().
+        */
+       KASSERT(p2->p_stat == SIDL,
+           ("cannot start forked process, bad status: %p", p2));
+       (void) splhigh();
+       p2->p_stat = SRUN;
+       setrunqueue(p2);
+       (void) spl0();
+
+       /*
+        * Now can be swapped.
+        */
+       PRELE(p1);
+
+       /*
+        * Preserve synchronization semantics of vfork.  If waiting for
+        * child to exec or exit, set P_PPWAIT on child, and sleep on our
+        * proc (in case of exit).
+        */
+       while (p2->p_flag & P_PPWAIT)
+               tsleep(p1, 0, "ppwait", 0);
+}
+