/*
 * Change priority of a thread sleeping in a turnstile.
 */
void
turnstile_change_pri(kthread_t *t, pri_t pri, pri_t *t_prip)
{
	sleepq_t *sqp = t->t_sleepq;

	sleepq_dequeue(t);
	*t_prip = pri;
	sleepq_insert(sqp, t);
}
/*
 * Remove thread from specified turnstile sleep queue; retrieve its
 * free turnstile; if it is the last waiter, delete the turnstile
 * from the turnstile chain and if there is an inheritor, delete it
 * from the inheritor's t_prioinv chain.
 */
static void
turnstile_dequeue(kthread_t *t)
{
	turnstile_t *ts = t->t_ts;
	turnstile_chain_t *tc = &TURNSTILE_CHAIN(ts->ts_sobj);
	turnstile_t *tsfree, **tspp;

	ASSERT(DISP_LOCK_HELD(&tc->tc_lock));
	ASSERT(t->t_lockp == &tc->tc_lock);

	if ((tsfree = ts->ts_free) != NULL) {
		ASSERT(ts->ts_waiters > 1);
		ASSERT(tsfree->ts_waiters == 0);
		t->t_ts = tsfree;
		ts->ts_free = tsfree->ts_free;
		tsfree->ts_free = NULL;
	} else {
		/*
		 * The active turnstile's freelist is empty, so this
		 * must be the last waiter.  Remove the turnstile
		 * from the hash chain and leave the now-inactive
		 * turnstile attached to the thread we're waking.
		 * Note that the ts_inheritor for the turnstile
		 * may be NULL. If one exists, its t_prioinv
		 * chain has to be updated.
		 */
		ASSERT(ts->ts_waiters == 1);
		if (ts->ts_inheritor != NULL) {
			(void) turnstile_pi_tsdelete(ts, ts->ts_inheritor);
			/*
			 * If we ever do a "disinherit" or "unboost", we need
			 * to do it only if "t" is a thread at the head of the
			 * sleep queue. Since the sleep queue is prioritized,
			 * the disinherit is necessary only if the interrupted
			 * thread is the highest priority thread.
			 * Otherwise, there is a higher priority thread blocked
			 * on the turnstile, whose inheritance cannot be
			 * disinherited. However, disinheriting is explicitly
			 * not done here, since it would require holding the
			 * inheritor's thread lock (see turnstile_unsleep()).
			 */
			ts->ts_inheritor = NULL;
		}
		tspp = &tc->tc_first;
		while (*tspp != ts)
			tspp = &(*tspp)->ts_next;
		*tspp = ts->ts_next;
		ASSERT(t->t_ts == ts);
	}
	ts->ts_waiters--;
	sleepq_dequeue(t);
	t->t_sobj_ops = NULL;
	t->t_wchan = NULL;
	t->t_wchan0 = NULL;
	ASSERT(t->t_state == TS_SLEEP);
}
Exemple #3
0
/*
 * Change the priority of a thread that's blocked on a condition variable.
 */
static void
cv_change_pri(kthread_t *t, pri_t pri, pri_t *t_prip)
{
	condvar_impl_t *cvp = (condvar_impl_t *)t->t_wchan;
	sleepq_t *sqp = t->t_sleepq;

	ASSERT(THREAD_LOCK_HELD(t));
	ASSERT(&SQHASH(cvp)->sq_queue == sqp);

	if (cvp == NULL)
		panic("cv_change_pri: %p not on sleep queue", t);
	sleepq_dequeue(t);
	*t_prip = pri;
	sleepq_insert(sqp, t);
}