summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_condvar.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2004-04-06 19:17:46 +0000
committerjhb <jhb@FreeBSD.org>2004-04-06 19:17:46 +0000
commit241908535b89498ae28f2dea48ae631b01dc6d28 (patch)
tree4a0a62119cab803f40317ae67cd3d91913ae1d00 /sys/kern/kern_condvar.c
parent7cf9a1d04483c8d713cf660b3184f87a848aaf68 (diff)
downloadFreeBSD-src-241908535b89498ae28f2dea48ae631b01dc6d28.zip
FreeBSD-src-241908535b89498ae28f2dea48ae631b01dc6d28.tar.gz
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.
Diffstat (limited to 'sys/kern/kern_condvar.c')
-rw-r--r--sys/kern/kern_condvar.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c
index 6fff7e0..2b7bd97 100644
--- a/sys/kern/kern_condvar.c
+++ b/sys/kern/kern_condvar.c
@@ -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);
+ }
}
OpenPOWER on IntegriCloud