svn commit: r297466 - head/sys/kern

John Baldwin jhb at FreeBSD.org
Thu Mar 31 18:10:30 UTC 2016


Author: jhb
Date: Thu Mar 31 18:10:29 2016
New Revision: 297466
URL: https://svnweb.freebsd.org/changeset/base/297466

Log:
  Rework handling of thread sleeps before timers are working.
  
  Previously, calls to *sleep() and cv_*wait*() immediately returned during
  early boot.  Instead, permit threads that request a sleep without a
  timeout to sleep as wakeup() works during early boot.  Sleeps with
  timeouts are harder to emulate without working timers, so just punt and
  panic explicitly if any thread tries to use those before timers are
  working.  Any threads that depend on timeouts should either wait until
  SI_SUB_KICK_SCHEDULER to start or they should use DELAY() until timers
  are available.
  
  Until APs are started earlier this should be a no-op as other kthreads
  shouldn't get a chance to start running until after timers are working
  regardless of when they were created.
  
  Reviewed by:	kib
  Sponsored by:	Netflix
  Differential Revision:	https://reviews.freebsd.org/D5724

Modified:
  head/sys/kern/kern_condvar.c
  head/sys/kern/kern_synch.c
  head/sys/kern/subr_sleepqueue.c

Modified: head/sys/kern/kern_condvar.c
==============================================================================
--- head/sys/kern/kern_condvar.c	Thu Mar 31 17:32:28 2016	(r297465)
+++ head/sys/kern/kern_condvar.c	Thu Mar 31 18:10:29 2016	(r297466)
@@ -122,15 +122,8 @@ _cv_wait(struct cv *cvp, struct lock_obj
 	    "Waiting on \"%s\"", cvp->cv_description);
 	class = LOCK_CLASS(lock);
 
-	if (cold || SCHEDULER_STOPPED()) {
-		/*
-		 * During autoconfiguration, just give interrupts
-		 * a chance, then just return.  Don't run any other
-		 * thread or panic below, in case this is the idle
-		 * process and already asleep.
-		 */
+	if (SCHEDULER_STOPPED())
 		return;
-	}
 
 	sleepq_lock(cvp);
 
@@ -183,13 +176,7 @@ _cv_wait_unlock(struct cv *cvp, struct l
 	    ("cv_wait_unlock cannot be used with Giant"));
 	class = LOCK_CLASS(lock);
 
-	if (cold || SCHEDULER_STOPPED()) {
-		/*
-		 * During autoconfiguration, just give interrupts
-		 * a chance, then just return.  Don't run any other
-		 * thread or panic below, in case this is the idle
-		 * process and already asleep.
-		 */
+	if (SCHEDULER_STOPPED()) {
 		class->lc_unlock(lock);
 		return;
 	}
@@ -240,15 +227,8 @@ _cv_wait_sig(struct cv *cvp, struct lock
 	    "Waiting on \"%s\"", cvp->cv_description);
 	class = LOCK_CLASS(lock);
 
-	if (cold || SCHEDULER_STOPPED()) {
-		/*
-		 * After a panic, or during autoconfiguration, just give
-		 * interrupts a chance, then just return; don't run any other
-		 * procs or panic below, in case this is the idle process and
-		 * already asleep.
-		 */
+	if (SCHEDULER_STOPPED())
 		return (0);
-	}
 
 	sleepq_lock(cvp);
 
@@ -307,15 +287,8 @@ _cv_timedwait_sbt(struct cv *cvp, struct
 	    "Waiting on \"%s\"", cvp->cv_description);
 	class = LOCK_CLASS(lock);
 
-	if (cold || SCHEDULER_STOPPED()) {
-		/*
-		 * After a panic, or during autoconfiguration, just give
-		 * interrupts a chance, then just return; don't run any other
-		 * thread or panic below, in case this is the idle process and
-		 * already asleep.
-		 */
-		return 0;
-	}
+	if (SCHEDULER_STOPPED())
+		return (0);
 
 	sleepq_lock(cvp);
 
@@ -376,15 +349,8 @@ _cv_timedwait_sig_sbt(struct cv *cvp, st
 	    "Waiting on \"%s\"", cvp->cv_description);
 	class = LOCK_CLASS(lock);
 
-	if (cold || SCHEDULER_STOPPED()) {
-		/*
-		 * After a panic, or during autoconfiguration, just give
-		 * interrupts a chance, then just return; don't run any other
-		 * thread or panic below, in case this is the idle process and
-		 * already asleep.
-		 */
-		return 0;
-	}
+	if (SCHEDULER_STOPPED())
+		return (0);
 
 	sleepq_lock(cvp);
 

Modified: head/sys/kern/kern_synch.c
==============================================================================
--- head/sys/kern/kern_synch.c	Thu Mar 31 17:32:28 2016	(r297465)
+++ head/sys/kern/kern_synch.c	Thu Mar 31 18:10:29 2016	(r297466)
@@ -162,15 +162,7 @@ _sleep(void *ident, struct lock_object *
 	else
 		class = NULL;
 
-	if (cold || SCHEDULER_STOPPED()) {
-		/*
-		 * During autoconfiguration, just return;
-		 * don't run any other threads or panic below,
-		 * in case this is the idle thread and already asleep.
-		 * XXX: this used to do "s = splhigh(); splx(safepri);
-		 * splx(s);" to give interrupts a chance, but there is
-		 * no way to give interrupts a chance now.
-		 */
+	if (SCHEDULER_STOPPED()) {
 		if (lock != NULL && priority & PDROP)
 			class->lc_unlock(lock);
 		return (0);
@@ -264,17 +256,8 @@ msleep_spin_sbt(void *ident, struct mtx 
 	KASSERT(p != NULL, ("msleep1"));
 	KASSERT(ident != NULL && TD_IS_RUNNING(td), ("msleep"));
 
-	if (cold || SCHEDULER_STOPPED()) {
-		/*
-		 * During autoconfiguration, just return;
-		 * don't run any other threads or panic below,
-		 * in case this is the idle thread and already asleep.
-		 * XXX: this used to do "s = splhigh(); splx(safepri);
-		 * splx(s);" to give interrupts a chance, but there is
-		 * no way to give interrupts a chance now.
-		 */
+	if (SCHEDULER_STOPPED())
 		return (0);
-	}
 
 	sleepq_lock(ident);
 	CTR5(KTR_PROC, "msleep_spin: thread %ld (pid %ld, %s) on %s (%p)",

Modified: head/sys/kern/subr_sleepqueue.c
==============================================================================
--- head/sys/kern/subr_sleepqueue.c	Thu Mar 31 17:32:28 2016	(r297465)
+++ head/sys/kern/subr_sleepqueue.c	Thu Mar 31 18:10:29 2016	(r297466)
@@ -385,6 +385,8 @@ sleepq_set_timeout_sbt(void *wchan, sbin
 	MPASS(TD_ON_SLEEPQ(td));
 	MPASS(td->td_sleepqueue == NULL);
 	MPASS(wchan != NULL);
+	if (cold)
+		panic("timed sleep before timers are working");
 	callout_reset_sbt_on(&td->td_slpcallout, sbt, pr,
 	    sleepq_timeout, td, PCPU_GET(cpuid), flags | C_DIRECT_EXEC);
 }


More information about the svn-src-head mailing list