svn commit: r342236 - in head/sys: kern sys
Mateusz Guzik
mjg at FreeBSD.org
Wed Dec 19 20:27:28 UTC 2018
Author: mjg
Date: Wed Dec 19 20:27:26 2018
New Revision: 342236
URL: https://svnweb.freebsd.org/changeset/base/342236
Log:
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
Modified:
head/sys/kern/kern_fork.c
head/sys/kern/subr_syscall.c
head/sys/sys/proc.h
Modified: head/sys/kern/kern_fork.c
==============================================================================
--- head/sys/kern/kern_fork.c Wed Dec 19 20:25:58 2018 (r342235)
+++ head/sys/kern/kern_fork.c Wed Dec 19 20:27:26 2018 (r342236)
@@ -757,6 +757,51 @@ do_fork(struct thread *td, struct fork_req *fr, struct
}
}
+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)
{
Modified: head/sys/kern/subr_syscall.c
==============================================================================
--- head/sys/kern/subr_syscall.c Wed Dec 19 20:25:58 2018 (r342235)
+++ head/sys/kern/subr_syscall.c Wed Dec 19 20:27:26 2018 (r342236)
@@ -165,7 +165,7 @@ syscallenter(struct thread *td)
static inline void
syscallret(struct thread *td, int error)
{
- struct proc *p, *p2;
+ struct proc *p;
struct syscall_args *sa;
ksiginfo_t ksi;
int traced, error1;
@@ -230,41 +230,6 @@ syscallret(struct thread *td, int error)
PROC_UNLOCK(p);
}
- if (__predict_false(td->td_pflags & TDP_RFPPWAIT)) {
- /*
- * 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);
- }
- }
+ if (__predict_false(td->td_pflags & TDP_RFPPWAIT))
+ fork_rfppwait(td);
}
Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h Wed Dec 19 20:25:58 2018 (r342235)
+++ head/sys/sys/proc.h Wed Dec 19 20:27:26 2018 (r342236)
@@ -1026,6 +1026,7 @@ int enterthispgrp(struct proc *p, struct pgrp *pgrp);
void faultin(struct proc *p);
void fixjobc(struct proc *p, struct pgrp *pgrp, int entering);
int fork1(struct thread *, struct fork_req *);
+void fork_rfppwait(struct thread *);
void fork_exit(void (*)(void *, struct trapframe *), void *,
struct trapframe *);
void fork_return(struct thread *, struct trapframe *);
More information about the svn-src-head
mailing list