platform/kvm: fix a race condition in vCPU.unlock()
Right now, it contains the code: origState := atomic.LoadUint32(&c.state) atomicbitops.AndUint32(&c.state, ^vCPUUser) The problem here is that vCPU.bounce that is called from another thread can add vCPUWaiter when origState has been read but vCPUUser isn't cleared yet. In this case, vCPU.unlock doesn't notify other threads about changes and c.bounce will be stuck in the futex_wait call. PiperOrigin-RevId: 389697411
This commit is contained in:
parent
34ec00c5e7
commit
14d6cb4436
|
@ -519,15 +519,21 @@ func (c *vCPU) lock() {
|
|||
//
|
||||
//go:nosplit
|
||||
func (c *vCPU) unlock() {
|
||||
if atomic.CompareAndSwapUint32(&c.state, vCPUUser|vCPUGuest, vCPUGuest) {
|
||||
origState := atomicbitops.CompareAndSwapUint32(&c.state, vCPUUser|vCPUGuest, vCPUGuest)
|
||||
if origState == vCPUUser|vCPUGuest {
|
||||
// Happy path: no exits are forced, and we can continue
|
||||
// executing on our merry way with a single atomic access.
|
||||
return
|
||||
}
|
||||
|
||||
// Clear the lock.
|
||||
origState := atomic.LoadUint32(&c.state)
|
||||
atomicbitops.AndUint32(&c.state, ^vCPUUser)
|
||||
for {
|
||||
state := atomicbitops.CompareAndSwapUint32(&c.state, origState, origState&^vCPUUser)
|
||||
if state == origState {
|
||||
break
|
||||
}
|
||||
origState = state
|
||||
}
|
||||
switch origState {
|
||||
case vCPUUser:
|
||||
// Normal state.
|
||||
|
|
Loading…
Reference in New Issue