/* * 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); }
/* * 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); }