Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 19 Dec 2018 20:27:26 +0000 (UTC)
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r342236 - in head/sys: kern sys
Message-ID:  <201812192027.wBJKRQZY074401@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 *);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201812192027.wBJKRQZY074401>