Page MenuHomeFreeBSD

Wakeup shared waiters on LK_DOWNGRADE
ActivePublic

Authored by mlaier on Apr 9 2015, 9:45 PM.
Index: sys/kern/kern_lock.c
===================================================================
--- sys/kern/kern_lock.c (revision 281338)
+++ sys/kern/kern_lock.c (working copy)
@@ -996,24 +996,48 @@ __lockmgr_args(struct lock *lk, u_int fl
}
TD_SLOCKS_INC(curthread);
/*
* In order to preserve waiters flags, just spin.
*/
for (;;) {
x = lk->lk_lock;
MPASS((x & LK_EXCLUSIVE_SPINNERS) == 0);
x &= LK_ALL_WAITERS;
- if (atomic_cmpset_rel_ptr(&lk->lk_lock, tid | x,
- LK_SHARERS_LOCK(1) | x))
- break;
- cpu_spinwait();
+ if ((x & LK_EXCLUSIVE_WAITERS) ||
+ !(x & LK_SHARED_WAITERS)) {
+ if (atomic_cmpset_rel_ptr(&lk->lk_lock, tid | x,
+ LK_SHARERS_LOCK(1) | x))
+ break;
+ cpu_spinwait();
+ continue;
+ }
+
+ sleepq_lock(&lk->lock_object);
+ x = lk->lk_lock;
+ x &= LK_ALL_WAITERS;
+
+ if ((x & LK_EXCLUSIVE_WAITERS) ||
+ !(x & LK_SHARED_WAITERS) ||
+ !atomic_cmpset_rel_ptr(&lk->lk_lock, tid | x,
+ LK_SHARERS_LOCK(1) | (x & ~LK_SHARED_WAITERS))) {
+ sleepq_release(&lk->lock_object);
+ continue;
+ }
+ LOCK_LOG2(lk,
+ "%s: %p waking up threads on the shared queue",
+ __func__, lk);
+ lk->lk_exslpfail = 0;
+ wakeup_swapper |= sleepq_broadcast(&lk->lock_object,
+ SLEEPQ_LK, 0, SQ_SHARED_QUEUE);
+ sleepq_release(&lk->lock_object);
+ break;
}
break;
case LK_RELEASE:
_lockmgr_assert(lk, KA_LOCKED, file, line);
x = lk->lk_lock;
if ((x & LK_SHARE) == 0) {
/*
* As first option, treact the lock as if it has not

Event Timeline

mlaier changed the title of this paste from untitled to Wakeup shared waiters on LK_DOWNGRADE.
mlaier updated the paste's language from autodetect to autodetect.