+ proc_limitdrop(p, 0);
+ p->p_limit = NULL;
+
+#if SYSV_SHM
+ /* Need to drop references to the shared memory segment(s), if any */
+ if (p->vm_shm) {
+ /*
+ * Use shmexec(): we have no address space, so no mappings
+ *
+ * XXX Yes, the routine is badly named.
+ */
+ shmexec(p);
+ }
+#endif
+
+ /* Need to undo the effects of the fdcopy(), if any */
+ fdfree(p);
+
+ /*
+ * Drop the reference on a text vnode pointer, if any
+ * XXX This code is broken in forkproc(); see <rdar://4256419>;
+ * XXX if anyone ever uses this field, we will be extremely unhappy.
+ */
+ if (p->p_textvp) {
+ vnode_rele(p->p_textvp);
+ p->p_textvp = NULL;
+ }
+
+ /* Stop the profiling clock */
+ stopprofclock(p);
+
+ /* Release the credential reference */
+ kauth_cred_unref(&p->p_ucred);
+
+ proc_list_lock();
+ /* Decrement the count of processes in the system */
+ nprocs--;
+ proc_list_unlock();
+
+ thread_call_free(p->p_rcall);
+
+ /* Free allocated memory */
+ FREE_ZONE(p->p_sigacts, sizeof *p->p_sigacts, M_SIGACTS);
+ FREE_ZONE(p->p_stats, sizeof *p->p_stats, M_PSTATS);
+ proc_checkdeadrefs(p);
+ FREE_ZONE(p, sizeof *p, M_PROC);
+}
+
+
+/*
+ * forkproc
+ *
+ * Description: Create a new process structure, given a parent process
+ * structure.
+ *
+ * Parameters: parent The parent process
+ * lock If the signal lock should be taken on
+ * the newly created process.
+ *
+ * Returns: !NULL The new process structure
+ * NULL Error (insufficient free memory)
+ *
+ * Note: When successful, the newly created process structure is
+ * partially initialized; if a caller needs to deconstruct the
+ * returned structure, they must call forkproc_free() to do so.
+ */
+proc_t
+forkproc(proc_t parent, int lock)
+{
+ struct proc * child; /* Our new process */
+ static int nextpid = 0, pidwrap = 0;
+ int error = 0;
+ struct session *sessp;
+ uthread_t uth_parent = (uthread_t)get_bsdthread_info(current_thread());
+
+ MALLOC_ZONE(child, proc_t , sizeof *child, M_PROC, M_WAITOK);
+ if (child == NULL) {
+ printf("forkproc: M_PROC zone exhausted\n");
+ goto bad;
+ }
+ /* zero it out as we need to insert in hash */
+ bzero(child, sizeof *child);
+
+ MALLOC_ZONE(child->p_stats, struct pstats *,
+ sizeof *child->p_stats, M_PSTATS, M_WAITOK);
+ if (child->p_stats == NULL) {
+ printf("forkproc: M_SUBPROC zone exhausted (p_stats)\n");
+ FREE_ZONE(child, sizeof *child, M_PROC);
+ child = NULL;
+ goto bad;
+ }
+ MALLOC_ZONE(child->p_sigacts, struct sigacts *,
+ sizeof *child->p_sigacts, M_SIGACTS, M_WAITOK);
+ if (child->p_sigacts == NULL) {
+ printf("forkproc: M_SUBPROC zone exhausted (p_sigacts)\n");
+ FREE_ZONE(child->p_stats, sizeof *child->p_stats, M_PSTATS);
+ FREE_ZONE(child, sizeof *child, M_PROC);
+ child = NULL;
+ goto bad;
+ }
+ child->p_rcall = thread_call_allocate((thread_call_func_t)realitexpire, child);
+ if (child->p_rcall == NULL) {
+ FREE_ZONE(child->p_sigacts, sizeof *child->p_sigacts, M_SIGACTS);
+ FREE_ZONE(child->p_stats, sizeof *child->p_stats, M_PSTATS);
+ FREE_ZONE(child, sizeof *child, M_PROC);
+ child = NULL;
+ goto bad;
+ }
+
+
+ /*
+ * Find an unused PID.
+ */
+
+ proc_list_lock();
+