locking/pvqspinlock: Fix double hash race
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 <wanpeng.li@hotmail.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Pan Xinhui <xinhui.pan@linux.vnet.ibm.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Waiman Long <Waiman.Long@hpe.com> Link: http://lkml.kernel.org/r/1468484156-4521-1-git-send-email-wanpeng.li@hotmail.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
2db34e8bf9
commit
229ce63157
|
@ -450,7 +450,7 @@ pv_wait_head_or_lock(struct qspinlock *lock, struct mcs_spinlock *node)
|
||||||
goto gotlock;
|
goto gotlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WRITE_ONCE(pn->state, vcpu_halted);
|
WRITE_ONCE(pn->state, vcpu_hashed);
|
||||||
qstat_inc(qstat_pv_wait_head, true);
|
qstat_inc(qstat_pv_wait_head, true);
|
||||||
qstat_inc(qstat_pv_wait_again, waitcnt);
|
qstat_inc(qstat_pv_wait_again, waitcnt);
|
||||||
pv_wait(&l->locked, _Q_SLOW_VAL);
|
pv_wait(&l->locked, _Q_SLOW_VAL);
|
||||||
|
|
Loading…
Reference in New Issue