Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Jan 2016 23:33:58 +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: r294472 - in head/sys: kern sys
Message-ID:  <201601202333.u0KNXwhK069298@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mjg
Date: Wed Jan 20 23:33:58 2016
New Revision: 294472
URL: https://svnweb.freebsd.org/changeset/base/294472

Log:
  session: avoid proctree lock on proc exit when possible
  
  We can get away with the common case with only proc lock held.
  
  Reviewed by:	kib

Modified:
  head/sys/kern/kern_exit.c
  head/sys/kern/kern_proc.c
  head/sys/sys/proc.h

Modified: head/sys/kern/kern_exit.c
==============================================================================
--- head/sys/kern/kern_exit.c	Wed Jan 20 23:27:02 2016	(r294471)
+++ head/sys/kern/kern_exit.c	Wed Jan 20 23:33:58 2016	(r294472)
@@ -189,7 +189,6 @@ exit1(struct thread *td, int rval, int s
 {
 	struct proc *p, *nq, *q, *t;
 	struct thread *tdt;
-	struct vnode *ttyvp = NULL;
 
 	mtx_assert(&Giant, MA_NOTOWNED);
 	KASSERT(rval == 0 || signo == 0, ("exit1 rv %d sig %d", rval, signo));
@@ -394,60 +393,9 @@ exit1(struct thread *td, int rval, int s
 	}
 
 	vmspace_exit(td);
-
-	sx_xlock(&proctree_lock);
-	if (SESS_LEADER(p)) {
-		struct session *sp = p->p_session;
-		struct tty *tp;
-
-		/*
-		 * s_ttyp is not zero'd; we use this to indicate that
-		 * the session once had a controlling terminal. (for
-		 * logging and informational purposes)
-		 */
-		SESS_LOCK(sp);
-		ttyvp = sp->s_ttyvp;
-		tp = sp->s_ttyp;
-		sp->s_ttyvp = NULL;
-		sp->s_ttydp = NULL;
-		sp->s_leader = NULL;
-		SESS_UNLOCK(sp);
-
-		/*
-		 * Signal foreground pgrp and revoke access to
-		 * controlling terminal if it has not been revoked
-		 * already.
-		 *
-		 * Because the TTY may have been revoked in the mean
-		 * time and could already have a new session associated
-		 * with it, make sure we don't send a SIGHUP to a
-		 * foreground process group that does not belong to this
-		 * session.
-		 */
-
-		if (tp != NULL) {
-			tty_lock(tp);
-			if (tp->t_session == sp)
-				tty_signal_pgrp(tp, SIGHUP);
-			tty_unlock(tp);
-		}
-
-		if (ttyvp != NULL) {
-			sx_xunlock(&proctree_lock);
-			if (vn_lock(ttyvp, LK_EXCLUSIVE) == 0) {
-				VOP_REVOKE(ttyvp, REVOKEALL);
-				VOP_UNLOCK(ttyvp, 0);
-			}
-			sx_xlock(&proctree_lock);
-		}
-	}
-	fixjobc(p, p->p_pgrp, 0);
-	sx_xunlock(&proctree_lock);
+	killjobc();
 	(void)acct_process(td);
 
-	/* Release the TTY now we've unlocked everything. */
-	if (ttyvp != NULL)
-		vrele(ttyvp);
 #ifdef KTRACE
 	ktrprocexit(td);
 #endif

Modified: head/sys/kern/kern_proc.c
==============================================================================
--- head/sys/kern/kern_proc.c	Wed Jan 20 23:27:02 2016	(r294471)
+++ head/sys/kern/kern_proc.c	Wed Jan 20 23:33:58 2016	(r294472)
@@ -686,6 +686,79 @@ fixjobc(struct proc *p, struct pgrp *pgr
 	}
 }
 
+void
+killjobc(void)
+{
+	struct session *sp;
+	struct tty *tp;
+	struct proc *p;
+	struct vnode *ttyvp;
+
+	p = curproc;
+	MPASS(p->p_flag & P_WEXIT);
+	/*
+	 * Do a quick check to see if there is anything to do with the
+	 * proctree_lock held. pgrp and LIST_EMPTY checks are for fixjobc().
+	 */
+	PROC_LOCK(p);
+	if (!SESS_LEADER(p) &&
+	    (p->p_pgrp == p->p_pptr->p_pgrp) &&
+	    LIST_EMPTY(&p->p_children)) {
+		PROC_UNLOCK(p);
+		return;
+	}
+	PROC_UNLOCK(p);
+
+	sx_xlock(&proctree_lock);
+	if (SESS_LEADER(p)) {
+		sp = p->p_session;
+
+		/*
+		 * s_ttyp is not zero'd; we use this to indicate that
+		 * the session once had a controlling terminal. (for
+		 * logging and informational purposes)
+		 */
+		SESS_LOCK(sp);
+		ttyvp = sp->s_ttyvp;
+		tp = sp->s_ttyp;
+		sp->s_ttyvp = NULL;
+		sp->s_ttydp = NULL;
+		sp->s_leader = NULL;
+		SESS_UNLOCK(sp);
+
+		/*
+		 * Signal foreground pgrp and revoke access to
+		 * controlling terminal if it has not been revoked
+		 * already.
+		 *
+		 * Because the TTY may have been revoked in the mean
+		 * time and could already have a new session associated
+		 * with it, make sure we don't send a SIGHUP to a
+		 * foreground process group that does not belong to this
+		 * session.
+		 */
+
+		if (tp != NULL) {
+			tty_lock(tp);
+			if (tp->t_session == sp)
+				tty_signal_pgrp(tp, SIGHUP);
+			tty_unlock(tp);
+		}
+
+		if (ttyvp != NULL) {
+			sx_xunlock(&proctree_lock);
+			if (vn_lock(ttyvp, LK_EXCLUSIVE) == 0) {
+				VOP_REVOKE(ttyvp, REVOKEALL);
+				VOP_UNLOCK(ttyvp, 0);
+			}
+			vrele(ttyvp);
+			sx_xlock(&proctree_lock);
+		}
+	}
+	fixjobc(p, p->p_pgrp, 0);
+	sx_xunlock(&proctree_lock);
+}
+
 /*
  * A process group has become orphaned;
  * if there are any stopped processes in the group,

Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h	Wed Jan 20 23:27:02 2016	(r294471)
+++ head/sys/sys/proc.h	Wed Jan 20 23:33:58 2016	(r294472)
@@ -938,6 +938,7 @@ void	fork_return(struct thread *, struct
 int	inferior(struct proc *p);
 void	kern_yield(int);
 void 	kick_proc0(void);
+void	killjobc(void);
 int	leavepgrp(struct proc *p);
 int	maybe_preempt(struct thread *td);
 void	maybe_yield(void);



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