PR kern/38761: new (?) race in buffer cache code

- Back out the previous workaround now that the sleep queue code has
  been changed to never let the queue become empty if there are valid
  waiters.
- Use sleepq_hashlock() to improve clarity.
- Sprinkle some assertions.
This commit is contained in:
ad 2008-06-16 10:03:47 +00:00
parent 461a5fb24b
commit 672f91757e
1 changed files with 15 additions and 14 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_condvar.c,v 1.23 2008/06/15 09:56:18 chris Exp $ */
/* $NetBSD: kern_condvar.c,v 1.24 2008/06/16 10:03:47 ad Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -30,15 +30,11 @@
*/
/*
* Kernel condition variable implementation, modeled after those found in
* Solaris, a description of which can be found in:
*
* Solaris Internals: Core Kernel Architecture, Jim Mauro and
* Richard McDougall.
* Kernel condition variable implementation.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_condvar.c,v 1.23 2008/06/15 09:56:18 chris Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_condvar.c,v 1.24 2008/06/16 10:03:47 ad Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@ -47,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_condvar.c,v 1.23 2008/06/15 09:56:18 chris Exp
#include <sys/condvar.h>
#include <sys/sleepq.h>
#include <sys/lockdebug.h>
#include <sys/cpu.h>
#include <uvm/uvm_extern.h>
@ -127,16 +124,18 @@ cv_enter(kcondvar_t *cv, kmutex_t *mtx, lwp_t *l)
kmutex_t *mp;
KASSERT(cv_is_valid(cv));
KASSERT(!cpu_intr_p());
KASSERT((l->l_pflag & LP_INTR) == 0 || panicstr != NULL);
LOCKDEBUG_LOCKED(CV_DEBUG_P(cv), cv, mtx, CV_RA, 0);
l->l_kpriority = true;
(void)sleeptab_lookup(&sleeptab, cv, &mp);
mp = sleepq_hashlock(cv);
sq = CV_SLEEPQ(cv);
sleepq_enter(sq, l, mp);
sleepq_enqueue(sq, cv, cv->cv_wmesg, &cv_syncobj);
mutex_exit(mtx);
KASSERT(cv_has_waiters(cv));
}
/*
@ -181,7 +180,7 @@ cv_unsleep(lwp_t *l, bool cleanup)
KASSERT(l->l_wchan == (wchan_t)cv);
KASSERT(l->l_sleepq == CV_SLEEPQ(cv));
KASSERT(cv_is_valid(cv));
KASSERT(!TAILQ_EMPTY(CV_SLEEPQ(cv)));
KASSERT(cv_has_waiters(cv));
return sleepq_unsleep(l, cleanup);
}
@ -279,7 +278,8 @@ cv_signal(kcondvar_t *cv)
/* LOCKDEBUG_WAKEUP(CV_DEBUG_P(cv), cv, CV_RA); */
KASSERT(cv_is_valid(cv));
cv_wakeup_one(cv);
if (__predict_false(!TAILQ_EMPTY(CV_SLEEPQ(cv))))
cv_wakeup_one(cv);
}
static void __noinline
@ -292,8 +292,8 @@ cv_wakeup_one(kcondvar_t *cv)
KASSERT(cv_is_valid(cv));
mp = sleepq_hashlock(cv);
sq = CV_SLEEPQ(cv);
(void)sleeptab_lookup(&sleeptab, cv, &mp);
l = TAILQ_FIRST(sq);
if (l == NULL) {
mutex_spin_exit(mp);
@ -328,7 +328,8 @@ cv_broadcast(kcondvar_t *cv)
/* LOCKDEBUG_WAKEUP(CV_DEBUG_P(cv), cv, CV_RA); */
KASSERT(cv_is_valid(cv));
cv_wakeup_all(cv);
if (__predict_false(!TAILQ_EMPTY(CV_SLEEPQ(cv))))
cv_wakeup_all(cv);
}
static void __noinline
@ -341,9 +342,9 @@ cv_wakeup_all(kcondvar_t *cv)
KASSERT(cv_is_valid(cv));
sq = CV_SLEEPQ(cv);
(void)sleeptab_lookup(&sleeptab, cv, &mp);
mp = sleepq_hashlock(cv);
swapin = 0;
sq = CV_SLEEPQ(cv);
for (l = TAILQ_FIRST(sq); l != NULL; l = next) {
KASSERT(l->l_sleepq == sq);
KASSERT(l->l_mutex == mp);