summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2001-01-24 10:47:14 +0000
committerjhb <jhb@FreeBSD.org>2001-01-24 10:47:14 +0000
commitf739ee572827baf1cd9569509411794ad9a187d2 (patch)
tree62f9a50d10e0d009133706712a7f93e321211f3a /sys
parentfdd3fb7200d897820ec117e80c3fbdcb978fcb99 (diff)
downloadFreeBSD-src-f739ee572827baf1cd9569509411794ad9a187d2.zip
FreeBSD-src-f739ee572827baf1cd9569509411794ad9a187d2.tar.gz
- Catch up to proc flag changes.
- Add new fork_exit() and fork_return() MI C functions.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_fork.c83
1 files changed, 79 insertions, 4 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index e8f8a60..4785a70 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -51,10 +51,12 @@
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
+#include <sys/syscall.h>
#include <sys/vnode.h>
#include <sys/acct.h>
#include <sys/ktr.h>
#include <sys/ktrace.h>
+#include <sys/kthread.h>
#include <sys/unistd.h>
#include <sys/jail.h>
@@ -273,7 +275,7 @@ fork1(p1, flags, procp)
p1->p_peers = newproc;
newproc->p_leader = p1->p_leader;
} else {
- newproc->p_peers = 0;
+ newproc->p_peers = NULL;
newproc->p_leader = newproc;
}
@@ -319,7 +321,7 @@ retry:
*/
p2 = LIST_FIRST(&allproc);
again:
- for (; p2 != 0; p2 = LIST_NEXT(p2, p_list)) {
+ for (; p2 != NULL; p2 = LIST_NEXT(p2, p_list)) {
while (p2->p_pid == trypid ||
p2->p_pgrp->pg_id == trypid ||
p2->p_session->s_sid == trypid) {
@@ -377,9 +379,12 @@ again:
* Increase reference counts on shared objects.
* The p_stats and p_sigacts substructs are set in vm_fork.
*/
- p2->p_flag = P_INMEM;
- if (p1->p_flag & P_PROFIL)
+ p2->p_flag = 0;
+ mtx_enter(&sched_lock, MTX_SPIN);
+ p2->p_sflag = PS_INMEM;
+ if (p1->p_sflag & PS_PROFIL)
startprofclock(p2);
+ mtx_exit(&sched_lock, MTX_SPIN);
MALLOC(p2->p_cred, struct pcred *, sizeof(struct pcred),
M_SUBPROC, M_WAITOK);
bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred));
@@ -631,3 +636,73 @@ rm_at_fork(function)
}
return (0);
}
+
+/*
+ * Handle the return of a child process from fork1(). This function
+ * is called from the MD fork_trampoline() entry point.
+ */
+void
+fork_exit(callout, arg, frame)
+ void *callout(void *, struct trapframe *);
+ void *arg;
+ struct trapframe frame;
+{
+ struct proc *p;
+
+ mtx_exit(&sched_lock, MTX_SPIN);
+ /*
+ * XXX: We really shouldn't have to do this.
+ */
+ enable_intr();
+
+#ifdef SMP
+ if (PCPU_GET(switchtime.tv_sec) == 0)
+ microuptime(PCPU_PTR(switchtime));
+ PCPU_SET(switchticks, ticks);
+#endif
+
+ /*
+ * cpu_set_fork_handler intercepts this function call to
+ * have this call a non-return function to stay in kernel mode.
+ * initproc has its own fork handler, but it does return.
+ */
+ (*callout)(arg, &frame);
+
+ /*
+ * Check if a kernel thread misbehaved and returned from its main
+ * function.
+ */
+ p = CURPROC;
+ if (p->p_flag & P_KTHREAD) {
+ mtx_enter(&Giant, MTX_DEF);
+ printf("Kernel thread \"%s\" (pid %d) exited prematurely.\n",
+ p->p_comm, p->p_pid);
+ kthread_exit(0);
+ }
+ mtx_assert(&Giant, MA_NOTOWNED);
+}
+
+/*
+ * Simplified back end of syscall(), used when returning from fork()
+ * directly into user mode. Giant is not held on entry, and must not
+ * be held on return. This function is passed in to fork_exit() as the
+ * first parameter and is called when returning to a new userland process.
+ */
+void
+fork_return(p, frame)
+ struct proc *p;
+ struct trapframe *frame;
+{
+
+ userret(p, frame, 0);
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET)) {
+ if (!mtx_owned(&Giant))
+ mtx_enter(&Giant, MTX_DEF);
+ ktrsysret(p->p_tracep, SYS_fork, 0, 0);
+ }
+#endif
+ if (mtx_owned(&Giant))
+ mtx_exit(&Giant, MTX_DEF);
+ mtx_assert(&Giant, MA_NOTOWNED);
+}
OpenPOWER on IntegriCloud