From 92f44a3f3c693167695ed564533c8b67cf76e142 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Mon, 12 Dec 2005 00:02:22 +0000 Subject: [PATCH] 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 --- sys/kern/kern_condvar.c | 49 ++++++++++++++++++++++++++++------------- sys/sys/condvar.h | 1 + 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c index 8ccea3aab414..ede6b61373bf 100644 --- a/sys/kern/kern_condvar.c +++ b/sys/kern/kern_condvar.c @@ -95,17 +95,8 @@ cv_destroy(struct cv *cvp) void cv_wait(struct cv *cvp, struct mtx *mp) { - struct thread *td; WITNESS_SAVE_DECL(mp); - td = curthread; -#ifdef KTRACE - if (KTRPOINT(td, KTR_CSW)) - ktrcsw(1, 0); -#endif - 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) { @@ -118,6 +109,40 @@ cv_wait(struct cv *cvp, struct mtx *mp) 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)) + ktrcsw(1, 0); +#endif + CV_ASSERT(cvp, mp, td); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &mp->mtx_object, + "Waiting on \"%s\"", cvp->cv_description); + + 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. + */ + mtx_unlock(mp); + return; + } + sleepq_lock(cvp); cvp->cv_waiters++; @@ -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 a8c9db72c0b1..97f699ab3453 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);