FreeBSD/sys/kern/subr_sleepqueue.c
/*
 * Time sleeping threads out.  When the timeout expires, the thread is
 * removed from the sleep queue and made runnable if it is still asleep.
 */
Time sleeping threads out.  When the timeout expires, the thread is
removed from the sleep queue and made runnable if it is still asleep.
Time sleeping threads out . When the timeout expires the thread is removed from the sleep queue and made runnable if it is still asleep .
static void
sleepq_timeout(void *arg)
{
	struct sleepqueue_chain *sc;
	struct sleepqueue *sq;
	struct thread *td;
	void *wchan;
	int wakeup_swapper;
	td = arg;
	wakeup_swapper = 0;
	CTR3(KTR_PROC, "sleepq_timeout: thread %p (pid %ld, %s)",
	    (void *)td, (long)td->td_proc->p_pid, (void *)td->td_name);
	thread_lock(td);
	if (TD_IS_SLEEPING(td) && TD_ON_SLEEPQ(td)) {
		wchan = td->td_wchan;
		sc = SC_LOOKUP(wchan);
		THREAD_LOCKPTR_ASSERT(td, &sc->sc_lock);
		sq = sleepq_lookup(wchan);
		MPASS(sq != NULL);
		td->td_flags |= TDF_TIMEOUT;
		wakeup_swapper = sleepq_resume_thread(sq, td, 0);
		thread_unlock(td);
		if (wakeup_swapper)
			kick_proc0();
		return;
	}
	if (TD_ON_SLEEPQ(td)) {
		td->td_flags |= TDF_TIMEOUT;
		thread_unlock(td);
		return;
	}
	if (td->td_flags & TDF_TIMEOUT) {
		MPASS(TD_IS_SLEEPING(td));
		td->td_flags &= ~TDF_TIMEOUT;
		TD_CLR_SLEEPING(td);
		wakeup_swapper = setrunnable(td);
	} else
		td->td_flags |= TDF_TIMOFAIL;
	thread_unlock(td);
	if (wakeup_swapper)
		kick_proc0();
}
static void sleepq_timeout ( void * arg ) { struct sleepqueue_chain * sc ; struct sleepqueue * sq ; struct thread * td ; void * wchan ; int wakeup_swapper ; td = arg ; wakeup_swapper = 0 ; CTR3 ( KTR_PROC , " " , ( void * ) td , ( long ) td -> td_proc -> p_pid , ( void * ) td -> td_name ) ; thread_lock ( td ) ; if ( TD_IS_SLEEPING ( td ) && TD_ON_SLEEPQ ( td ) ) { wchan = td -> td_wchan ; sc = SC_LOOKUP ( wchan ) ; THREAD_LOCKPTR_ASSERT ( td , & sc -> sc_lock ) ; sq = sleepq_lookup ( wchan ) ; MPASS ( sq != NULL ) ; td -> td_flags |= TDF_TIMEOUT ; wakeup_swapper = sleepq_resume_thread ( sq , td , 0 ) ; thread_unlock ( td ) ; if ( wakeup_swapper ) kick_proc0 ( ) ; return ; } if ( TD_ON_SLEEPQ ( td ) ) { td -> td_flags |= TDF_TIMEOUT ; thread_unlock ( td ) ; return ; } if ( td -> td_flags & TDF_TIMEOUT ) { MPASS ( TD_IS_SLEEPING ( td ) ) ; td -> td_flags &= ~ TDF_TIMEOUT ; TD_CLR_SLEEPING ( td ) ; wakeup_swapper = setrunnable ( td ) ; } else td -> td_flags |= TDF_TIMOFAIL ; thread_unlock ( td ) ; if ( wakeup_swapper ) kick_proc0 ( ) ; }
Time sleeping threads out.
Time sleeping threads out .
/*
	 * First, see if the thread is asleep and get the wait channel if
	 * it is.
	 */ /*
	 * If the thread is on the SLEEPQ but isn't sleeping yet, it
	 * can either be on another CPU in between sleepq_add() and
	 * one of the sleepq_*wait*() routines or it can be in
	 * sleepq_catch_signals().
	 */ /*
	 * Now check for the edge cases.  First, if TDF_TIMEOUT is set,
	 * then the other thread has already yielded to us, so clear
	 * the flag and resume it.  If TDF_TIMEOUT is not set, then the
	 * we know that the other thread is not on a sleep queue, but it
	 * hasn't resumed execution yet.  In that case, set TDF_TIMOFAIL
	 * to let it know that the timeout has already run and doesn't
	 * need to be canceled.
	 */