FreeBSD/sys/kern/subr_sleepqueue.c
/*
 * Marks the pending sleep of the current thread as interruptible and
 * makes an initial check for pending signals before putting a thread
 * to sleep. Enters and exits with the thread lock held.  Thread lock
 * may have transitioned from the sleepq lock to a run lock.
 */
Marks the pending sleep of the current thread as interruptible and
makes an initial check for pending signals before putting a thread
to sleep. Enters and exits with the thread lock held.  Thread lock
may have transitioned from the sleepq lock to a run lock.
Marks the pending sleep of the current thread as interruptible and makes an initial check for pending signals before putting a thread to sleep . Enters and exits with the thread lock held . Thread lock may have transitioned from the sleepq lock to a run lock .
static int
sleepq_catch_signals(void *wchan, int pri)
{
	struct sleepqueue_chain *sc;
	struct sleepqueue *sq;
	struct thread *td;
	struct proc *p;
	struct sigacts *ps;
	int sig, ret;
	td = curthread;
	p = curproc;
	sc = SC_LOOKUP(wchan);
	mtx_assert(&sc->sc_lock, MA_OWNED);
	MPASS(wchan != NULL);
	if ((td->td_pflags & TDP_WAKEUP) != 0) {
		td->td_pflags &= ~TDP_WAKEUP;
		ret = EINTR;
		thread_lock(td);
		goto out;
	}
	thread_lock(td);
	if ((td->td_flags & (TDF_NEEDSIGCHK | TDF_NEEDSUSPCHK)) == 0) {
		sleepq_switch(wchan, pri);
		return (0);
	}
	thread_unlock(td);
	mtx_unlock_spin(&sc->sc_lock);
	CTR3(KTR_PROC, "sleepq catching signals: thread %p (pid %ld, %s)",
		(void *)td, (long)p->p_pid, td->td_name);
	PROC_LOCK(p);
	ps = p->p_sigacts;
	mtx_lock(&ps->ps_mtx);
	sig = cursig(td);
	if (sig == -1) {
		mtx_unlock(&ps->ps_mtx);
		KASSERT((td->td_flags & TDF_SBDRY) != 0, ("lost TDF_SBDRY"));
		KASSERT(TD_SBDRY_INTR(td),
		    ("lost TDF_SERESTART of TDF_SEINTR"));
		KASSERT((td->td_flags & (TDF_SEINTR | TDF_SERESTART)) !=
		    (TDF_SEINTR | TDF_SERESTART),
		    ("both TDF_SEINTR and TDF_SERESTART"));
		ret = TD_SBDRY_ERRNO(td);
	} else if (sig == 0) {
		mtx_unlock(&ps->ps_mtx);
		ret = thread_suspend_check(1);
		MPASS(ret == 0 || ret == EINTR || ret == ERESTART);
	} else {
		if (SIGISMEMBER(ps->ps_sigintr, sig))
			ret = EINTR;
		else
			ret = ERESTART;
		mtx_unlock(&ps->ps_mtx);
	}
	PROC_SLOCK(p);
	mtx_lock_spin(&sc->sc_lock);
	PROC_UNLOCK(p);
	thread_lock(td);
	PROC_SUNLOCK(p);
	if (ret == 0) {
		sleepq_switch(wchan, pri);
		return (0);
	}
out:
	if (TD_ON_SLEEPQ(td)) {
		sq = sleepq_lookup(wchan);
		if (sleepq_resume_thread(sq, td, 0)) {
#ifdef INVARIANTS
			panic("not waking up swapper");
#endif
		}
	}
	mtx_unlock_spin(&sc->sc_lock);
	MPASS(td->td_lock != &sc->sc_lock);
	return (ret);
}
static int sleepq_catch_signals ( void * wchan , int pri ) { struct sleepqueue_chain * sc ; struct sleepqueue * sq ; struct thread * td ; struct proc * p ; struct sigacts * ps ; int sig , ret ; td = curthread ; p = curproc ; sc = SC_LOOKUP ( wchan ) ; mtx_assert ( & sc -> sc_lock , MA_OWNED ) ; MPASS ( wchan != NULL ) ; if ( ( td -> td_pflags & TDP_WAKEUP ) != 0 ) { td -> td_pflags &= ~ TDP_WAKEUP ; ret = EINTR ; thread_lock ( td ) ; goto out ; } thread_lock ( td ) ; if ( ( td -> td_flags & ( TDF_NEEDSIGCHK | TDF_NEEDSUSPCHK ) ) == 0 ) { sleepq_switch ( wchan , pri ) ; return ( 0 ) ; } thread_unlock ( td ) ; mtx_unlock_spin ( & sc -> sc_lock ) ; CTR3 ( KTR_PROC , " " , ( void * ) td , ( long ) p -> p_pid , td -> td_name ) ; PROC_LOCK ( p ) ; ps = p -> p_sigacts ; mtx_lock ( & ps -> ps_mtx ) ; sig = cursig ( td ) ; if ( sig == -1 ) { mtx_unlock ( & ps -> ps_mtx ) ; KASSERT ( ( td -> td_flags & TDF_SBDRY ) != 0 , ( " " ) ) ; KASSERT ( TD_SBDRY_INTR ( td ) , ( " " ) ) ; KASSERT ( ( td -> td_flags & ( TDF_SEINTR | TDF_SERESTART ) ) != ( TDF_SEINTR | TDF_SERESTART ) , ( " " ) ) ; ret = TD_SBDRY_ERRNO ( td ) ; } else if ( sig == 0 ) { mtx_unlock ( & ps -> ps_mtx ) ; ret = thread_suspend_check ( 1 ) ; MPASS ( ret == 0 || ret == EINTR || ret == ERESTART ) ; } else { if ( SIGISMEMBER ( ps -> ps_sigintr , sig ) ) ret = EINTR ; else ret = ERESTART ; mtx_unlock ( & ps -> ps_mtx ) ; } PROC_SLOCK ( p ) ; mtx_lock_spin ( & sc -> sc_lock ) ; PROC_UNLOCK ( p ) ; thread_lock ( td ) ; PROC_SUNLOCK ( p ) ; if ( ret == 0 ) { sleepq_switch ( wchan , pri ) ; return ( 0 ) ; } out : if ( TD_ON_SLEEPQ ( td ) ) { sq = sleepq_lookup ( wchan ) ; if ( sleepq_resume_thread ( sq , td , 0 ) ) { #ifdef INVARIANTS panic ( " " ) ; #endif } } mtx_unlock_spin ( & sc -> sc_lock ) ; MPASS ( td -> td_lock != & sc -> sc_lock ) ; return ( ret ) ; }
Marks the pending sleep of the current thread as interruptible and
 makes an initial check for pending signals before putting a thread
 to sleep.
Marks the pending sleep of the current thread as interruptible and makes an initial check for pending signals before putting a thread to sleep .
/*
	 * See if there are any pending signals for this thread.  If not
	 * we can switch immediately.  Otherwise do the signal processing
	 * directly.
	 */ /*
	 * Lock the per-process spinlock prior to dropping the PROC_LOCK
	 * to avoid a signal delivery race.  PROC_LOCK, PROC_SLOCK, and
	 * thread_lock() are currently held in tdsendsignal().
	 */ /*
	 * There were pending signals and this thread is still
	 * on the sleep queue, remove it from the sleep queue.
	 */ /*
			 * This thread hasn't gone to sleep yet, so it
			 * should not be swapped out.
			 */