Don't acquire contended lock with the OS thread locked.

Fixes #1049

PiperOrigin-RevId: 297175164
This commit is contained in:
Adin Scannell 2020-02-25 12:21:27 -08:00 committed by gVisor bot
parent 53504e29ca
commit 98b693e61b
1 changed files with 17 additions and 1 deletions

View File

@ -329,10 +329,12 @@ func (m *machine) Destroy() {
}
// Get gets an available vCPU.
//
// This will return with the OS thread locked.
func (m *machine) Get() *vCPU {
m.mu.RLock()
runtime.LockOSThread()
tid := procid.Current()
m.mu.RLock()
// Check for an exact match.
if c := m.vCPUs[tid]; c != nil {
@ -343,8 +345,22 @@ func (m *machine) Get() *vCPU {
// The happy path failed. We now proceed to acquire an exclusive lock
// (because the vCPU map may change), and scan all available vCPUs.
// In this case, we first unlock the OS thread. Otherwise, if mu is
// not available, the current system thread will be parked and a new
// system thread spawned. We avoid this situation by simply refreshing
// tid after relocking the system thread.
m.mu.RUnlock()
runtime.UnlockOSThread()
m.mu.Lock()
runtime.LockOSThread()
tid = procid.Current()
// Recheck for an exact match.
if c := m.vCPUs[tid]; c != nil {
c.lock()
m.mu.Unlock()
return c
}
for {
// Scan for an available vCPU.