Esempio n. 1
0
/*
 * Wake up a thread blocked in a turnstile. Used to enable interruptibility
 * of threads blocked on a SOBJ_USER_PI sobj.
 *
 * The implications of this interface are:
 *
 * 1. turnstile_block() may return with an EINTR.
 * 2. When the owner of an sobj releases it, but no turnstile is found (i.e.
 *    no waiters), the (prior) owner must call turnstile_pi_recalc() to
 *    waive any priority inherited from interrupted waiters.
 *
 * When a waiter is interrupted, disinheriting its willed priority from the
 * inheritor would require holding the inheritor's thread lock, while also
 * holding the waiter's thread lock which is a turnstile lock. If the
 * inheritor's thread lock is not free, and is also a turnstile lock that
 * is out of lock order, the waiter's thread lock would have to be dropped.
 * This leads to complications for the caller of turnstile_unsleep(), since
 * the caller holds the waiter's thread lock. So, instead of disinheriting
 * on waiter interruption, the owner is required to follow rule 2 above.
 *
 * Avoiding disinherit on waiter interruption seems acceptable because
 * the owner runs at an unnecessarily high priority only while sobj is held,
 * which it would have done in any case, if the waiter had not been interrupted.
 */
void
turnstile_unsleep(kthread_t *t)
{
	turnstile_dequeue(t);
	THREAD_TRANSITION(t);
	CL_SETRUN(t);
}
Esempio n. 2
0
/*
 * Wakeup a thread sleeping on a semaphore, and put it
 * on the dispatch queue.
 * Called via SOBJ_UNSLEEP().
 */
static void
sema_unsleep(kthread_t *t)
{
	kthread_t	**tpp;
	kthread_t	*tp;
	sema_impl_t	*s;

	ASSERT(THREAD_LOCK_HELD(t));
	s = (sema_impl_t *)t->t_wchan;
	tpp = &s->s_slpq;
	while ((tp = *tpp) != NULL) {
		if (tp == t) {
			*tpp = t->t_link;
			t->t_link = NULL;
			t->t_sobj_ops = NULL;
			t->t_wchan = NULL;
			t->t_wchan0 = NULL;
			/*
			 * Change thread to transition state and
			 * drop the semaphore sleep queue lock.
			 */
			THREAD_TRANSITION(t);
			CL_SETRUN(t);
			return;
		}
		tpp = &tp->t_link;
	}
}
Esempio n. 3
0
/*
 * Place the thread in question on the run q.
 */
static void
shuttle_unsleep(kthread_t *t)
{
	ASSERT(THREAD_LOCK_HELD(t));

	/* Waiting on a shuttle */
	ASSERT(t->t_wchan0 == (caddr_t)1 && t->t_wchan == NULL);
	t->t_flag &= ~T_WAKEABLE;
	t->t_wchan0 = NULL;
	t->t_sobj_ops = NULL;
	THREAD_TRANSITION(t);
	CL_SETRUN(t);
}
Esempio n. 4
0
static void
waitq_dequeue(waitq_t *wq, kthread_t *t)
{
	ASSERT(THREAD_LOCK_HELD(t));
	ASSERT(t->t_waitq == wq);
	ASSERT(ISWAITING(t));

	waitq_unlink(wq, t);
	DTRACE_SCHED1(cpucaps__wakeup, kthread_t *, t);

	/*
	 * Change thread to transition state and drop the wait queue lock. The
	 * thread will remain locked since its t_lockp points to the
	 * transition_lock.
	 */
	THREAD_TRANSITION(t);
}