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
This commit is contained in:
parent
ac3c9819ab
commit
b4f1d267b7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=297466
@ -122,15 +122,8 @@ _cv_wait(struct cv *cvp, struct lock_object *lock)
|
||||
"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 lock_object *lock)
|
||||
("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_object *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 lock_object *lock, sbintime_t sbt,
|
||||
"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, struct lock_object *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
|
||||
* thread or panic below, in case this is the idle process and
|
||||
* already asleep.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
if (SCHEDULER_STOPPED())
|
||||
return (0);
|
||||
|
||||
sleepq_lock(cvp);
|
||||
|
||||
|
@ -162,15 +162,7 @@ _sleep(void *ident, struct lock_object *lock, int priority,
|
||||
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 *mtx, const char *wmesg,
|
||||
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)",
|
||||
|
@ -385,6 +385,8 @@ sleepq_set_timeout_sbt(void *wchan, sbintime_t sbt, sbintime_t pr,
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user