From fdd67930a0f2fec891e4be9c2b62996eb8b06ce5 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 13 Nov 2021 14:36:35 -0800 Subject: [PATCH] sync: in TryLock try to acquire mutex even if state is not 0 For #45435 Change-Id: I728accd9a53c1826243f52aa04dc2a0a1dfdaadf Reviewed-on: https://go-review.googlesource.com/c/go/+/363672 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Dmitry Vyukov --- src/sync/mutex.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/sync/mutex.go b/src/sync/mutex.go index 9dd04d947017f..18b2cedba72f8 100644 --- a/src/sync/mutex.go +++ b/src/sync/mutex.go @@ -87,13 +87,22 @@ func (m *Mutex) Lock() { // and use of TryLock is often a sign of a deeper problem // in a particular use of mutexes. func (m *Mutex) TryLock() bool { - if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) { - if race.Enabled { - race.Acquire(unsafe.Pointer(m)) - } - return true + old := m.state + if old&(mutexLocked|mutexStarving) != 0 { + return false + } + + // There may be a goroutine waiting for the mutex, but we are + // running now and can try to grab the mutex before that + // goroutine wakes up. + if !atomic.CompareAndSwapInt32(&m.state, old, old|mutexLocked) { + return false + } + + if race.Enabled { + race.Acquire(unsafe.Pointer(m)) } - return false + return true } func (m *Mutex) lockSlow() {