diff --git a/src/runtime/sema.go b/src/runtime/sema.go index 18e0a398ba..f848515ae2 100644 --- a/src/runtime/sema.go +++ b/src/runtime/sema.go @@ -62,8 +62,8 @@ func poll_runtime_Semacquire(addr *uint32) { } //go:linkname sync_runtime_Semrelease sync.runtime_Semrelease -func sync_runtime_Semrelease(addr *uint32, handoff bool) { - semrelease1(addr, handoff) +func sync_runtime_Semrelease(addr *uint32, handoff bool, skipframes int) { + semrelease1(addr, handoff, skipframes) } //go:linkname sync_runtime_SemacquireMutex sync.runtime_SemacquireMutex @@ -153,10 +153,10 @@ func semacquire1(addr *uint32, lifo bool, profile semaProfileFlags) { } func semrelease(addr *uint32) { - semrelease1(addr, false) + semrelease1(addr, false, 0) } -func semrelease1(addr *uint32, handoff bool) { +func semrelease1(addr *uint32, handoff bool, skipframes int) { root := semroot(addr) atomic.Xadd(addr, 1) @@ -183,7 +183,7 @@ func semrelease1(addr *uint32, handoff bool) { if s != nil { // May be slow, so unlock first acquiretime := s.acquiretime if acquiretime != 0 { - mutexevent(t0-acquiretime, 3) + mutexevent(t0-acquiretime, 3+skipframes) } if s.ticket != 0 { throw("corrupted semaphore ticket") @@ -191,7 +191,7 @@ func semrelease1(addr *uint32, handoff bool) { if handoff && cansemacquire(addr) { s.ticket = 1 } - readyWithTime(s, 5) + readyWithTime(s, 5+skipframes) } } diff --git a/src/sync/mutex.go b/src/sync/mutex.go index 4c5582c809..a809993fe0 100644 --- a/src/sync/mutex.go +++ b/src/sync/mutex.go @@ -180,6 +180,14 @@ func (m *Mutex) Unlock() { // Fast path: drop lock bit. new := atomic.AddInt32(&m.state, -mutexLocked) + if new != 0 { + // Outlined slow path to allow inlining the fast path. + // To hide unlockSlow during tracing we skip one extra frame when tracing GoUnblock. + m.unlockSlow(new) + } +} + +func (m *Mutex) unlockSlow(new int32) { if (new+mutexLocked)&mutexLocked == 0 { throw("sync: unlock of unlocked mutex") } @@ -198,7 +206,7 @@ func (m *Mutex) Unlock() { // Grab the right to wake someone. new = (old - 1<