+ thread_t child_thread;
+ int err;
+
+ if ((err = fork1(parent_proc, &child_thread, PROC_CREATE_VFORK)) != 0) {
+ retval[1] = 0;
+ } else {
+ /*
+ * kludge: rely on uu_proc being set in the vfork case,
+ * rather than returning the actual thread. We can remove
+ * this when we remove the uu_proc/current_proc() kludge.
+ */
+ proc_t child_proc = current_proc();
+
+ retval[0] = child_proc->p_pid;
+ retval[1] = 1; /* flag child return for user space */
+
+ /*
+ * Drop the signal lock on the child which was taken on our
+ * behalf by forkproc()/cloneproc() to prevent signals being
+ * received by the child in a partially constructed state.
+ */
+ proc_signalend(child_proc, 0);
+ proc_transend(child_proc, 0);
+
+ /* flag the fork has occurred */
+ proc_knote(parent_proc, NOTE_FORK | child_proc->p_pid);
+ DTRACE_PROC1(create, proc_t, child_proc);
+ }
+
+ return(err);
+}
+
+
+/*
+ * fork1
+ *
+ * Description: common code used by all new process creation other than the
+ * bootstrap of the initial process on the system
+ *
+ * Parameters: parent_proc parent process of the process being
+ * child_threadp pointer to location to receive the
+ * Mach thread_t of the child process
+ * breated
+ * kind kind of creation being requested
+ *
+ * Notes: Permissable values for 'kind':
+ *
+ * PROC_CREATE_FORK Create a complete process which will
+ * return actively running in both the
+ * parent and the child; the child copies
+ * the parent address space.
+ * PROC_CREATE_SPAWN Create a complete process which will
+ * return actively running in the parent
+ * only after returning actively running
+ * in the child; the child address space
+ * is newly created by an image activator,
+ * after which the child is run.
+ * PROC_CREATE_VFORK Creates a partial process which will
+ * borrow the parent task, thread, and
+ * uthread to return running in the child;
+ * the child address space and other parts
+ * are lazily created at execve() time, or
+ * the child is terminated, and the parent
+ * does not actively run until that
+ * happens.
+ *
+ * At first it may seem strange that we return the child thread
+ * address rather than process structure, since the process is
+ * the only part guaranteed to be "new"; however, since we do
+ * not actualy adjust other references between Mach and BSD (see
+ * the block diagram above the implementation of vfork()), this
+ * is the only method which guarantees us the ability to get
+ * back to the other information.
+ */
+int
+fork1(proc_t parent_proc, thread_t *child_threadp, int kind)
+{
+ thread_t parent_thread = (thread_t)current_thread();
+ uthread_t parent_uthread = (uthread_t)get_bsdthread_info(parent_thread);
+ proc_t child_proc = NULL; /* set in switch, but compiler... */
+ thread_t child_thread = NULL;