diff options
author | jhb <jhb@FreeBSD.org> | 2001-01-24 10:47:14 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2001-01-24 10:47:14 +0000 |
commit | f739ee572827baf1cd9569509411794ad9a187d2 (patch) | |
tree | 62f9a50d10e0d009133706712a7f93e321211f3a /sys | |
parent | fdd3fb7200d897820ec117e80c3fbdcb978fcb99 (diff) | |
download | FreeBSD-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.c | 83 |
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); +} |