diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2018-12-19 20:27:26 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2018-12-19 20:27:26 +0000 |
commit | 7d065d876e1e220bcd4f0f9a833b07b7a61bcd4e (patch) | |
tree | e77b79806bc3ea325538972f2c8a3656b88ab15d /sys/kern/kern_fork.c | |
parent | 1ea91370aee7a939446e29391ee4e706c83356be (diff) | |
download | src-7d065d876e1e220bcd4f0f9a833b07b7a61bcd4e.tar.gz src-7d065d876e1e220bcd4f0f9a833b07b7a61bcd4e.zip |
Deinline vfork handling out of the syscall return path.
vfork is rarely called (comparatively to other syscalls) and it avoidably
pollutes the fast path.
Sponsored by: The FreeBSD Foundation
Notes
Notes:
svn path=/head/; revision=342236
Diffstat (limited to 'sys/kern/kern_fork.c')
-rw-r--r-- | sys/kern/kern_fork.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index acba58b89c8f..f897f78b48ca 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -757,6 +757,51 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread * } } +void +fork_rfppwait(struct thread *td) +{ + struct proc *p, *p2; + + MPASS(td->td_pflags & TDP_RFPPWAIT); + + p = td->td_proc; + /* + * Preserve synchronization semantics of vfork. If + * waiting for child to exec or exit, fork set + * P_PPWAIT on child, and there we sleep on our proc + * (in case of exit). + * + * Do it after the ptracestop() above is finished, to + * not block our debugger until child execs or exits + * to finish vfork wait. + */ + td->td_pflags &= ~TDP_RFPPWAIT; + p2 = td->td_rfppwait_p; +again: + PROC_LOCK(p2); + while (p2->p_flag & P_PPWAIT) { + PROC_LOCK(p); + if (thread_suspend_check_needed()) { + PROC_UNLOCK(p2); + thread_suspend_check(0); + PROC_UNLOCK(p); + goto again; + } else { + PROC_UNLOCK(p); + } + cv_timedwait(&p2->p_pwait, &p2->p_mtx, hz); + } + PROC_UNLOCK(p2); + + if (td->td_dbgflags & TDB_VFORK) { + PROC_LOCK(p); + if (p->p_ptevents & PTRACE_VFORK) + ptracestop(td, SIGTRAP, NULL); + td->td_dbgflags &= ~TDB_VFORK; + PROC_UNLOCK(p); + } +} + int fork1(struct thread *td, struct fork_req *fr) { |