/* * the semaphore is granted when the semaphore's * count is greater than zero and blocks when equal * to zero. */ void sema_p(ksema_t *sp) { sema_impl_t *s; disp_lock_t *sqlp; s = (sema_impl_t *)sp; sqlp = &SQHASH(s)->sq_lock; disp_lock_enter(sqlp); ASSERT(s->s_count >= 0); while (s->s_count == 0) { if (panicstr) { disp_lock_exit(sqlp); return; } thread_lock_high(curthread); SEMA_BLOCK(s, sqlp); thread_unlock_nopreempt(curthread); swtch(); disp_lock_enter(sqlp); } s->s_count--; disp_lock_exit(sqlp); }
void cv_broadcast(kcondvar_t *cvp) { condvar_impl_t *cp = (condvar_impl_t *)cvp; /* make sure the cv_waiters field looks sane */ ASSERT(cp->cv_waiters <= CV_MAX_WAITERS); if (cp->cv_waiters > 0) { sleepq_head_t *sqh = SQHASH(cp); disp_lock_enter(&sqh->sq_lock); ASSERT(CPU_ON_INTR(CPU) == 0); sleepq_wakeall_chan(&sqh->sq_queue, cp); cp->cv_waiters = 0; disp_lock_exit(&sqh->sq_lock); } }
/* * try to acquire the semaphore. if the semaphore is greater than * zero, then the semaphore is granted and returns 1. otherwise * return 0. */ int sema_tryp(ksema_t *sp) { sema_impl_t *s; sleepq_head_t *sqh; int gotit = 0; s = (sema_impl_t *)sp; sqh = SQHASH(s); disp_lock_enter(&sqh->sq_lock); if (s->s_count > 0) { s->s_count--; gotit = 1; } disp_lock_exit(&sqh->sq_lock); return (gotit); }
/* * Wake threads that are blocked in a turnstile. */ void turnstile_wakeup(turnstile_t *ts, int qnum, int nthreads, kthread_t *owner) { turnstile_chain_t *tc = &TURNSTILE_CHAIN(ts->ts_sobj); sleepq_t *sqp = &ts->ts_sleepq[qnum]; ASSERT(DISP_LOCK_HELD(&tc->tc_lock)); /* * Waive any priority we may have inherited from this turnstile. */ if (ts->ts_inheritor != NULL) { turnstile_pi_waive(ts); } while (nthreads-- > 0) { kthread_t *t = sqp->sq_first; ASSERT(t->t_ts == ts); ASSERT(ts->ts_waiters > 1 || ts->ts_inheritor == NULL); DTRACE_SCHED1(wakeup, kthread_t *, t); turnstile_dequeue(t); CL_WAKEUP(t); /* previous thread lock, tc_lock, not dropped */ /* * If the caller did direct handoff of ownership, * make the new owner inherit from this turnstile. */ if (t == owner) { kthread_t *wp = ts->ts_sleepq[TS_WRITER_Q].sq_first; kthread_t *rp = ts->ts_sleepq[TS_READER_Q].sq_first; pri_t wpri = wp ? DISP_PRIO(wp) : 0; pri_t rpri = rp ? DISP_PRIO(rp) : 0; turnstile_pi_inherit(ts, t, MAX(wpri, rpri)); owner = NULL; } thread_unlock_high(t); /* drop run queue lock */ } if (owner != NULL) panic("turnstile_wakeup: owner %p not woken", (void *)owner); disp_lock_exit(&tc->tc_lock); }
/* * Drop the lock protecting the hash chain for sobj. */ void turnstile_exit(void *sobj) { disp_lock_exit(&TURNSTILE_CHAIN(sobj).tc_lock); }
/* * similiar to sema_p except that it blocks at an interruptible * priority. if a signal is present then return 1 otherwise 0. */ int sema_p_sig(ksema_t *sp) { kthread_t *t = curthread; klwp_t *lwp = ttolwp(t); sema_impl_t *s; disp_lock_t *sqlp; if (lwp == NULL) { sema_p(sp); return (0); } s = (sema_impl_t *)sp; sqlp = &SQHASH(s)->sq_lock; disp_lock_enter(sqlp); ASSERT(s->s_count >= 0); while (s->s_count == 0) { proc_t *p = ttoproc(t); thread_lock_high(t); t->t_flag |= T_WAKEABLE; SEMA_BLOCK(s, sqlp); lwp->lwp_asleep = 1; lwp->lwp_sysabort = 0; thread_unlock_nopreempt(t); if (ISSIG(t, JUSTLOOKING) || MUSTRETURN(p, t)) setrun(t); swtch(); t->t_flag &= ~T_WAKEABLE; if (ISSIG(t, FORREAL) || lwp->lwp_sysabort || MUSTRETURN(p, t)) { kthread_t *sq, *tp; lwp->lwp_asleep = 0; lwp->lwp_sysabort = 0; disp_lock_enter(sqlp); sq = s->s_slpq; /* * in case sema_v and interrupt happen * at the same time, we need to pass the * sema_v to the next thread. */ if ((sq != NULL) && (s->s_count > 0)) { tp = sq; ASSERT(THREAD_LOCK_HELD(tp)); sq = sq->t_link; tp->t_link = NULL; DTRACE_SCHED1(wakeup, kthread_t *, tp); tp->t_sobj_ops = NULL; tp->t_wchan = NULL; ASSERT(tp->t_state == TS_SLEEP); CL_WAKEUP(tp); s->s_slpq = sq; disp_lock_exit_high(sqlp); thread_unlock(tp); } else { disp_lock_exit(sqlp); } return (1); } lwp->lwp_asleep = 0; disp_lock_enter(sqlp); } s->s_count--; disp_lock_exit(sqlp); return (0); }