keep track of what file/line the locks were grabbed on

This commit is contained in:
Wade Simmons 2023-05-09 11:51:02 -04:00
parent a83f0ca470
commit e5789770b1

View File

@ -5,12 +5,13 @@ package nebula
import ( import (
"fmt" "fmt"
"runtime"
"sync" "sync"
"github.com/timandy/routine" "github.com/timandy/routine"
) )
var threadLocal routine.ThreadLocal = routine.NewThreadLocalWithInitial(func() any { return map[mutexKey]bool{} }) var threadLocal routine.ThreadLocal = routine.NewThreadLocalWithInitial(func() any { return map[mutexKey]mutexValue{} })
type mutexKey struct { type mutexKey struct {
Type string Type string
@ -18,6 +19,11 @@ type mutexKey struct {
ID uint32 ID uint32
} }
type mutexValue struct {
file string
line int
}
type syncRWMutex struct { type syncRWMutex struct {
sync.RWMutex sync.RWMutex
mutexKey mutexKey
@ -29,50 +35,54 @@ func newSyncRWMutex(key mutexKey) syncRWMutex {
} }
} }
func checkMutex(state map[mutexKey]bool, add mutexKey) { func checkMutex(state map[mutexKey]mutexValue, add mutexKey) {
switch add.Type { switch add.Type {
case "hostinfo": case "hostinfo":
// Check for any other hostinfo keys: // Check for any other hostinfo keys:
for k, v := range state { for k := range state {
if k.Type == "hostinfo" && v { if k.Type == "hostinfo" {
panic(fmt.Errorf("grabbing hostinfo lock and already have a hostinfo lock: state=%v add=%v", state, add)) panic(fmt.Errorf("grabbing hostinfo lock and already have a hostinfo lock: state=%v add=%v", state, add))
} }
} }
if state[mutexKey{Type: "hostmap", SubType: "main"}] { if _, ok := state[mutexKey{Type: "hostmap", SubType: "main"}]; ok {
panic(fmt.Errorf("grabbing hostinfo lock and already have hostmap-main: state=%v add=%v", state, add)) panic(fmt.Errorf("grabbing hostinfo lock and already have hostmap-main: state=%v add=%v", state, add))
} }
if state[mutexKey{Type: "hostmap", SubType: "pending"}] { if _, ok := state[mutexKey{Type: "hostmap", SubType: "pending"}]; ok {
panic(fmt.Errorf("grabbing hostinfo lock and already have hostmap-pending: state=%v add=%v", state, add)) panic(fmt.Errorf("grabbing hostinfo lock and already have hostmap-pending: state=%v add=%v", state, add))
} }
case "hostmap-pending": case "hostmap-pending":
if state[mutexKey{Type: "hostmap", SubType: "main"}] { if _, ok := state[mutexKey{Type: "hostmap", SubType: "main"}]; ok {
panic(fmt.Errorf("grabbing hostmap-pending lock and already have hostmap-main: state=%v add=%v", state, add)) panic(fmt.Errorf("grabbing hostmap-pending lock and already have hostmap-main: state=%v add=%v", state, add))
} }
} }
} }
func (s *syncRWMutex) Lock() { func (s *syncRWMutex) Lock() {
m := threadLocal.Get().(map[mutexKey]bool) m := threadLocal.Get().(map[mutexKey]mutexValue)
checkMutex(m, s.mutexKey) checkMutex(m, s.mutexKey)
m[s.mutexKey] = true v := mutexValue{}
_, v.file, v.line, _ = runtime.Caller(1)
m[s.mutexKey] = v
s.RWMutex.Lock() s.RWMutex.Lock()
} }
func (s *syncRWMutex) Unlock() { func (s *syncRWMutex) Unlock() {
m := threadLocal.Get().(map[mutexKey]bool) m := threadLocal.Get().(map[mutexKey]mutexValue)
delete(m, s.mutexKey) delete(m, s.mutexKey)
s.RWMutex.Unlock() s.RWMutex.Unlock()
} }
func (s *syncRWMutex) RLock() { func (s *syncRWMutex) RLock() {
m := threadLocal.Get().(map[mutexKey]bool) m := threadLocal.Get().(map[mutexKey]mutexValue)
checkMutex(m, s.mutexKey) checkMutex(m, s.mutexKey)
m[s.mutexKey] = true v := mutexValue{}
_, v.file, v.line, _ = runtime.Caller(1)
m[s.mutexKey] = v
s.RWMutex.RLock() s.RWMutex.RLock()
} }
func (s *syncRWMutex) RUnlock() { func (s *syncRWMutex) RUnlock() {
m := threadLocal.Get().(map[mutexKey]bool) m := threadLocal.Get().(map[mutexKey]mutexValue)
delete(m, s.mutexKey) delete(m, s.mutexKey)
s.RWMutex.RUnlock() s.RWMutex.RUnlock()
} }