diff options
author | attilio <attilio@FreeBSD.org> | 2010-01-07 00:47:50 +0000 |
---|---|---|
committer | attilio <attilio@FreeBSD.org> | 2010-01-07 00:47:50 +0000 |
commit | 2e14be290b5b8c1dd99a985297642637367d2604 (patch) | |
tree | 15f9f7f63468c6f258e3e3f4d51a51c0dac511a9 /sys/kern | |
parent | 9b6b3618fec2df610c856eeeb69b75306239e21a (diff) | |
download | FreeBSD-src-2e14be290b5b8c1dd99a985297642637367d2604.zip FreeBSD-src-2e14be290b5b8c1dd99a985297642637367d2604.tar.gz |
Exclusive waiters sleeping with LK_SLEEPFAIL on and using interruptible
sleeps/timeout may have left spourious lk_exslpfail counts on, so clean
it up even when accessing a shared queue acquisition, giving to
lk_exslpfail the value of 'upper limit'.
In the worst case scenario, infact (mixed
interruptible sleep / LK_SLEEPFAIL waiters) what may happen is that both
queues are awaken even if that's not necessary, but still no harm.
Reported by: Lucius Windschuh <lwindschuh at googlemail dot com>
Reviewed by: kib
Tested by: pho, Lucius Windschuh <lwindschuh at googlemail dot com>
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_lock.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index 531c851..6783a43 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -300,7 +300,14 @@ wakeupshlk(struct lock *lk, const char *file, int line) } } else { - MPASS(lk->lk_exslpfail == 0); + + /* + * Exclusive waiters sleeping with LK_SLEEPFAIL on + * and using interruptible sleeps/timeout may have + * left spourious lk_exslpfail counts on, so clean + * it up anyway. + */ + lk->lk_exslpfail = 0; queue = SQ_SHARED_QUEUE; } @@ -959,7 +966,14 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, queue = SQ_SHARED_QUEUE; } } else { - MPASS(lk->lk_exslpfail == 0); + + /* + * Exclusive waiters sleeping with LK_SLEEPFAIL + * on and using interruptible sleeps/timeout + * may have left spourious lk_exslpfail counts + * on, so clean it up anyway. + */ + lk->lk_exslpfail = 0; queue = SQ_SHARED_QUEUE; } @@ -1037,8 +1051,16 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, queue = SQ_EXCLUSIVE_QUEUE; v &= ~LK_EXCLUSIVE_WAITERS; } else { + + /* + * Exclusive waiters sleeping with + * LK_SLEEPFAIL on and using + * interruptible sleeps/timeout may + * have left spourious lk_exslpfail + * counts on, so clean it up anyway. + */ MPASS(v & LK_SHARED_WAITERS); - MPASS(lk->lk_exslpfail == 0); + lk->lk_exslpfail = 0; queue = SQ_SHARED_QUEUE; v &= ~LK_SHARED_WAITERS; } |