diff options
author | rodrigc <rodrigc@FreeBSD.org> | 2005-12-12 00:02:22 +0000 |
---|---|---|
committer | rodrigc <rodrigc@FreeBSD.org> | 2005-12-12 00:02:22 +0000 |
commit | 4377e3b906f68937a8dca335993c27b24923c9c3 (patch) | |
tree | 193e281b1a05b4ca90f96954bb92e5d56807fc8a | |
parent | 16b60b222455d355c26bee796cfca71f5b34f6cc (diff) | |
download | FreeBSD-src-4377e3b906f68937a8dca335993c27b24923c9c3.zip FreeBSD-src-4377e3b906f68937a8dca335993c27b24923c9c3.tar.gz |
Contributions from XFS for FreeBSD project:
- Implement cv_wait_unlock() method which has semantics compatible
with the sv_wait() method in IRIX. For cv_wait_unlock(), the lock
must be held before entering the function, but is not held when the
function is exited.
- Implement the existing cv_wait() function in terms of cv_wait_unlock().
Submitted by: kan
Feedback from: jhb, trhodes, Christoph Hellwig <hch at infradead dot org>
-rw-r--r-- | sys/kern/kern_condvar.c | 35 | ||||
-rw-r--r-- | sys/sys/condvar.h | 1 |
2 files changed, 28 insertions, 8 deletions
diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c index 8ccea3a..ede6b61 100644 --- a/sys/kern/kern_condvar.c +++ b/sys/kern/kern_condvar.c @@ -95,9 +95,34 @@ cv_destroy(struct cv *cvp) void cv_wait(struct cv *cvp, struct mtx *mp) { - struct thread *td; WITNESS_SAVE_DECL(mp); + WITNESS_SAVE(&mp->mtx_object, mp); + + if (cold || panicstr) { + /* + * During autoconfiguration, just give interrupts + * a chance, then just return. Don't run any other + * thread or panic below, in case this is the idle + * process and already asleep. + */ + return; + } + + cv_wait_unlock(cvp, mp); + mtx_lock(mp); + WITNESS_RESTORE(&mp->mtx_object, mp); +} + +/* + * Wait on a condition variable. This function differs from cv_wait by + * not aquiring the mutex after condition variable was signaled. + */ +void +cv_wait_unlock(struct cv *cvp, struct mtx *mp) +{ + struct thread *td; + td = curthread; #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) @@ -106,7 +131,6 @@ cv_wait(struct cv *cvp, struct mtx *mp) CV_ASSERT(cvp, mp, td); WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &mp->mtx_object, "Waiting on \"%s\"", cvp->cv_description); - WITNESS_SAVE(&mp->mtx_object, mp); if (cold || panicstr) { /* @@ -115,6 +139,7 @@ cv_wait(struct cv *cvp, struct mtx *mp) * thread or panic below, in case this is the idle * process and already asleep. */ + mtx_unlock(mp); return; } @@ -127,13 +152,7 @@ cv_wait(struct cv *cvp, struct mtx *mp) sleepq_add(cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR); sleepq_wait(cvp); -#ifdef KTRACE - if (KTRPOINT(td, KTR_CSW)) - ktrcsw(0, 0); -#endif PICKUP_GIANT(); - mtx_lock(mp); - WITNESS_RESTORE(&mp->mtx_object, mp); } /* diff --git a/sys/sys/condvar.h b/sys/sys/condvar.h index a8c9db7..97f699a 100644 --- a/sys/sys/condvar.h +++ b/sys/sys/condvar.h @@ -53,6 +53,7 @@ void cv_init(struct cv *cvp, const char *desc); void cv_destroy(struct cv *cvp); void cv_wait(struct cv *cvp, struct mtx *mp); +void cv_wait_unlock(struct cv *cvp, struct mtx *mp); int cv_wait_sig(struct cv *cvp, struct mtx *mp); int cv_timedwait(struct cv *cvp, struct mtx *mp, int timo); int cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo); |