mutex.go 962 B

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