Debug cv_destroy() with mutex held

There still appears to be a race in the condition variables where
->cv_mutex is set after we are woken from the cv_destroy wait queue.
This might be possible when cv_destroy() is called immediately after
cv_broadcast().  We had some troubles with this previously but
there may still be a small race, see commit d599e4f.

The following patch closes one small race and improves the ASSERTs
such that they log the offending value.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
zfsonlinux/zfs#943
This commit is contained in:
Brian Behlendorf 2012-09-07 11:05:46 -07:00
parent 95331f4437
commit 3c60f5054c

View File

@ -63,7 +63,8 @@ EXPORT_SYMBOL(__cv_init);
static int
cv_destroy_wakeup(kcondvar_t *cvp)
{
if ((waitqueue_active(&cvp->cv_event)) ||
if ((cvp->cv_mutex != NULL) ||
(waitqueue_active(&cvp->cv_event)) ||
(atomic_read(&cvp->cv_waiters) > 0))
return 0;
@ -81,9 +82,9 @@ __cv_destroy(kcondvar_t *cvp)
while (cv_destroy_wakeup(cvp) == 0)
wait_event_timeout(cvp->cv_destroy, cv_destroy_wakeup(cvp), 1);
ASSERT(cvp->cv_mutex == NULL);
ASSERT(atomic_read(&cvp->cv_waiters) == 0);
ASSERT(!waitqueue_active(&cvp->cv_event));
ASSERT3P(cvp->cv_mutex, ==, NULL);
ASSERT3S(atomic_read(&cvp->cv_waiters), ==, 0);
ASSERT3S(waitqueue_active(&cvp->cv_event), ==, 0);
SEXIT;
}