1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
package sync
import (
"runtime"
"sync"
"time"
)
type Mutex struct {
mu sync.Mutex
hold *int // Unique value for passing to pprof.
stack [32]uintptr // The stack for the current holder.
start time.Time // When the lock was obtained.
entries int // Number of entries returned from runtime.Callers.
}
func (m *Mutex) Lock() {
if contentionOn {
v := new(int)
lockBlockers.Add(v, 0)
m.mu.Lock()
lockBlockers.Remove(v)
m.hold = v
lockHolders.Add(v, 0)
} else {
m.mu.Lock()
}
if lockTimesOn {
m.entries = runtime.Callers(2, m.stack[:])
m.start = time.Now()
}
}
func (m *Mutex) Unlock() {
if lockTimesOn {
d := time.Since(m.start)
var key [32]uintptr
copy(key[:], m.stack[:m.entries])
lockStatsMu.Lock()
v, ok := lockStatsByStack[key]
if !ok {
v.Init()
}
v.Add(d)
lockStatsByStack[key] = v
lockStatsMu.Unlock()
}
if contentionOn {
lockHolders.Remove(m.hold)
}
m.mu.Unlock()
}
|