svn commit: r334062 - head/sys/kern

Mateusz Guzik mjg at FreeBSD.org
Tue May 22 19:24:58 UTC 2018


Author: mjg
Date: Tue May 22 19:24:57 2018
New Revision: 334062
URL: https://svnweb.freebsd.org/changeset/base/334062

Log:
  Move preemption handling out of critical_exit.
  
  In preperataion for making the enter/exit pair inline.
  
  Reviewed by:	kib

Modified:
  head/sys/kern/kern_switch.c

Modified: head/sys/kern/kern_switch.c
==============================================================================
--- head/sys/kern/kern_switch.c	Tue May 22 19:11:06 2018	(r334061)
+++ head/sys/kern/kern_switch.c	Tue May 22 19:24:57 2018	(r334062)
@@ -209,48 +209,49 @@ critical_enter(void)
 	    (long)td->td_proc->p_pid, td->td_name, td->td_critnest);
 }
 
-void
-critical_exit(void)
+static void __noinline
+critical_exit_preempt(void)
 {
 	struct thread *td;
 	int flags;
 
 	td = curthread;
-	KASSERT(td->td_critnest != 0,
-	    ("critical_exit: td_critnest == 0"));
+	KASSERT(td->td_owepreempt != 0,
+	    ("critical_exit: td_owepreempt == 0"));
+	if (td->td_critnest != 0)
+		return;
+	if (kdb_active)
+		return;
 
-	if (td->td_critnest == 1) {
-		td->td_critnest = 0;
+	/*
+	 * Microoptimization: we committed to switch,
+	 * disable preemption in interrupt handlers
+	 * while spinning for the thread lock.
+	 */
+	td->td_critnest = 1;
+	thread_lock(td);
+	td->td_critnest--;
+	flags = SW_INVOL | SW_PREEMPT;
+	if (TD_IS_IDLETHREAD(td))
+		flags |= SWT_IDLE;
+	else
+		flags |= SWT_OWEPREEMPT;
+	mi_switch(flags, NULL);
+	thread_unlock(td);
+}
 
-		/*
-		 * Interrupt handlers execute critical_exit() on
-		 * leave, and td_owepreempt may be left set by an
-		 * interrupt handler only when td_critnest > 0.  If we
-		 * are decrementing td_critnest from 1 to 0, read
-		 * td_owepreempt after decrementing, to not miss the
-		 * preempt.  Disallow compiler to reorder operations.
-		 */
-		__compiler_membar();
-		if (td->td_owepreempt && !kdb_active) {
-			/*
-			 * Microoptimization: we committed to switch,
-			 * disable preemption in interrupt handlers
-			 * while spinning for the thread lock.
-			 */
-			td->td_critnest = 1;
-			thread_lock(td);
-			td->td_critnest--;
-			flags = SW_INVOL | SW_PREEMPT;
-			if (TD_IS_IDLETHREAD(td))
-				flags |= SWT_IDLE;
-			else
-				flags |= SWT_OWEPREEMPT;
-			mi_switch(flags, NULL);
-			thread_unlock(td);
-		}
-	} else
-		td->td_critnest--;
+void
+critical_exit(void)
+{
+	struct thread *td;
 
+	td = curthread;
+	KASSERT(td->td_critnest != 0,
+	    ("critical_exit: td_critnest == 0"));
+	td->td_critnest--;
+	__compiler_membar();
+	if (__predict_false(td->td_owepreempt))
+		critical_exit_preempt();
 	CTR4(KTR_CRITICAL, "critical_exit by thread %p (%ld, %s) to %d", td,
 	    (long)td->td_proc->p_pid, td->td_name, td->td_critnest);
 }


More information about the svn-src-head mailing list