MCPcopy Create free account
hub / github.com/F-Stack/f-stack / sleepq_switch

Function sleepq_switch

freebsd/kern/subr_sleepqueue.c:545–612  ·  view source on GitHub ↗

* Switches to another thread if we are still asleep on a sleep queue. * Returns with thread lock. */

Source from the content-addressed store, hash-verified

543 * Returns with thread lock.
544 */
545static void
546sleepq_switch(const void *wchan, int pri)
547{
548 struct sleepqueue_chain *sc;
549 struct sleepqueue *sq;
550 struct thread *td;
551 bool rtc_changed;
552
553 td = curthread;
554 sc = SC_LOOKUP(wchan);
555 mtx_assert(&sc->sc_lock, MA_OWNED);
556 THREAD_LOCK_ASSERT(td, MA_OWNED);
557
558 /*
559 * If we have a sleep queue, then we've already been woken up, so
560 * just return.
561 */
562 if (td->td_sleepqueue != NULL) {
563 mtx_unlock_spin(&sc->sc_lock);
564 thread_unlock(td);
565 return;
566 }
567
568 /*
569 * If TDF_TIMEOUT is set, then our sleep has been timed out
570 * already but we are still on the sleep queue, so dequeue the
571 * thread and return.
572 *
573 * Do the same if the real-time clock has been adjusted since this
574 * thread calculated its timeout based on that clock. This handles
575 * the following race:
576 * - The Ts thread needs to sleep until an absolute real-clock time.
577 * It copies the global rtc_generation into curthread->td_rtcgen,
578 * reads the RTC, and calculates a sleep duration based on that time.
579 * See umtxq_sleep() for an example.
580 * - The Tc thread adjusts the RTC, bumps rtc_generation, and wakes
581 * threads that are sleeping until an absolute real-clock time.
582 * See tc_setclock() and the POSIX specification of clock_settime().
583 * - Ts reaches the code below. It holds the sleepqueue chain lock,
584 * so Tc has finished waking, so this thread must test td_rtcgen.
585 * (The declaration of td_rtcgen refers to this comment.)
586 */
587 rtc_changed = td->td_rtcgen != 0 && td->td_rtcgen != rtc_generation;
588 if ((td->td_flags & TDF_TIMEOUT) || rtc_changed) {
589 if (rtc_changed) {
590 td->td_rtcgen = 0;
591 }
592 MPASS(TD_ON_SLEEPQ(td));
593 sq = sleepq_lookup(wchan);
594 sleepq_remove_thread(sq, td);
595 mtx_unlock_spin(&sc->sc_lock);
596 thread_unlock(td);
597 return;
598 }
599#ifdef SLEEPQUEUE_PROFILING
600 if (prof_enabled)
601 sleepq_profile(td->td_wmesg);
602#endif

Callers 3

sleepq_catch_signalsFunction · 0.85
sleepq_waitFunction · 0.85
sleepq_timedwaitFunction · 0.85

Calls 7

mtx_assertFunction · 0.85
sleepq_lookupFunction · 0.85
sleepq_remove_threadFunction · 0.85
sleepq_profileFunction · 0.85
thread_lock_setFunction · 0.85
sched_sleepFunction · 0.70
mi_switchFunction · 0.70

Tested by

no test coverage detected