projects
/
openwrt
/
staging
/
blogic.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
| inline |
side by side
(parent:
2db34e8
)
locking/pvqspinlock: Fix double hash race
author
Wanpeng Li
<
[email protected]
>
Thu, 14 Jul 2016 08:15:56 +0000
(16:15 +0800)
committer
Ingo Molnar
<
[email protected]
>
Wed, 10 Aug 2016 12:13:28 +0000
(14:13 +0200)
When the lock holder vCPU is racing with the queue head:
CPU 0 (lock holder) CPU1 (queue head)
=================== =================
spin_lock(); spin_lock();
pv_kick_node(): pv_wait_head_or_lock():
if (!lp) {
lp = pv_hash(lock, pn);
xchg(&l->locked, _Q_SLOW_VAL);
}
WRITE_ONCE(pn->state, vcpu_halted);
cmpxchg(&pn->state,
vcpu_halted, vcpu_hashed);
WRITE_ONCE(l->locked, _Q_SLOW_VAL);
(void)pv_hash(lock, pn);
In this case, lock holder inserts the pv_node of queue head into the
hash table and set _Q_SLOW_VAL unnecessary. This patch avoids it by
restoring/setting vcpu_hashed state after failing adaptive locking
spinning.
Signed-off-by: Wanpeng Li <
[email protected]
>
Signed-off-by: Peter Zijlstra (Intel) <
[email protected]
>
Reviewed-by: Pan Xinhui <
[email protected]
>
Cc: Andrew Morton <
[email protected]
>
Cc: Davidlohr Bueso <
[email protected]
>
Cc: Linus Torvalds <
[email protected]
>
Cc: Paul E. McKenney <
[email protected]
>
Cc: Peter Zijlstra <
[email protected]
>
Cc: Thomas Gleixner <
[email protected]
>
Cc: Waiman Long <
[email protected]
>
Link:
http://lkml.kernel.org/r/
[email protected]
Signed-off-by: Ingo Molnar <
[email protected]
>
kernel/locking/qspinlock_paravirt.h
patch
|
blob
|
history
diff --git
a/kernel/locking/qspinlock_paravirt.h
b/kernel/locking/qspinlock_paravirt.h
index 37649e69056cf974e27d0137260f8ff46ad688df..8a99abf58080be21fbb954777b48aca24d4342b5 100644
(file)
--- a/
kernel/locking/qspinlock_paravirt.h
+++ b/
kernel/locking/qspinlock_paravirt.h
@@
-450,7
+450,7
@@
pv_wait_head_or_lock(struct qspinlock *lock, struct mcs_spinlock *node)
goto gotlock;
}
}
- WRITE_ONCE(pn->state, vcpu_ha
lt
ed);
+ WRITE_ONCE(pn->state, vcpu_ha
sh
ed);
qstat_inc(qstat_pv_wait_head, true);
qstat_inc(qstat_pv_wait_again, waitcnt);
pv_wait(&l->locked, _Q_SLOW_VAL);