Associate a simple count of waiters with each condition variable. The

count is protected by the mutex that protects the condition, so the count
does not require any extra locking or atomic operations.  It serves as an
optimization to avoid calling into the sleepqueue code at all if there are
no waiters.

Note that the count can get temporarily out of sync when threads sleeping
on a condition variable time out or are aborted.  However, it doesn't hurt
to call the sleepqueue code for either a signal or a broadcast when there
are no waiters, and the count is never out of sync in the opposite
direction unless we have more than INT_MAX sleeping threads.
This commit is contained in:
John Baldwin 2004-04-06 19:17:46 +00:00
parent 535eb30962
commit 9000d57d57
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=127954
2 changed files with 18 additions and 3 deletions

View File

@ -65,6 +65,7 @@ cv_init(struct cv *cvp, const char *desc)
{
cvp->cv_description = desc;
cvp->cv_waiters = 0;
}
/*
@ -119,6 +120,7 @@ cv_wait(struct cv *cvp, struct mtx *mp)
sq = sleepq_lookup(cvp);
cvp->cv_waiters++;
DROP_GIANT();
mtx_unlock(mp);
@ -175,6 +177,7 @@ cv_wait_sig(struct cv *cvp, struct mtx *mp)
/* XXX: Missing the threading checks from msleep! */
cvp->cv_waiters++;
DROP_GIANT();
mtx_unlock(mp);
@ -241,6 +244,7 @@ cv_timedwait(struct cv *cvp, struct mtx *mp, int timo)
sq = sleepq_lookup(cvp);
cvp->cv_waiters++;
DROP_GIANT();
mtx_unlock(mp);
@ -299,6 +303,7 @@ cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo)
sq = sleepq_lookup(cvp);
cvp->cv_waiters++;
DROP_GIANT();
mtx_unlock(mp);
@ -341,7 +346,10 @@ void
cv_signal(struct cv *cvp)
{
sleepq_signal(cvp, SLEEPQ_CONDVAR, -1);
if (cvp->cv_waiters > 0) {
cvp->cv_waiters--;
sleepq_signal(cvp, SLEEPQ_CONDVAR, -1);
}
}
/*
@ -352,5 +360,8 @@ void
cv_broadcastpri(struct cv *cvp, int pri)
{
sleepq_broadcast(cvp, SLEEPQ_CONDVAR, pri);
if (cvp->cv_waiters > 0) {
cvp->cv_waiters = 0;
sleepq_broadcast(cvp, SLEEPQ_CONDVAR, pri);
}
}

View File

@ -38,10 +38,14 @@ struct thread;
TAILQ_HEAD(cv_waitq, thread);
/*
* Condition variable.
* Condition variable. The waiters count is protected by the mutex that
* protects the condition; that is, the mutex that is passed to cv_wait*()
* and is held across calls to cv_signal() and cv_broadcast(). It is an
* optimization to avoid looking up the sleep queue if there are no waiters.
*/
struct cv {
const char *cv_description;
int cv_waiters;
};
#ifdef _KERNEL