mirror of
https://github.com/slackhq/nebula.git
synced 2025-11-09 03:23:57 +01:00
112 lines
2.7 KiB
Go
112 lines
2.7 KiB
Go
//go:build mutex_debug
|
|
// +build mutex_debug
|
|
|
|
package nebula
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"runtime"
|
|
"runtime/debug"
|
|
"sync"
|
|
|
|
"github.com/timandy/routine"
|
|
)
|
|
|
|
var threadLocal routine.ThreadLocal = routine.NewThreadLocalWithInitial(func() any { return map[mutexKey]mutexValue{} })
|
|
|
|
type mutexKeyType string
|
|
|
|
const (
|
|
mutexKeyTypeHostMap mutexKeyType = "hostmap"
|
|
mutexKeyTypeHostInfo = "hostinfo"
|
|
mutexKeyTypeHandshakeManager = "handshake-manager"
|
|
)
|
|
|
|
type mutexKey struct {
|
|
Type mutexKeyType
|
|
ID uint32
|
|
}
|
|
|
|
type mutexValue struct {
|
|
file string
|
|
line int
|
|
}
|
|
|
|
type syncRWMutex struct {
|
|
sync.RWMutex
|
|
mutexKey
|
|
}
|
|
|
|
func newSyncRWMutex(key mutexKey) syncRWMutex {
|
|
return syncRWMutex{
|
|
mutexKey: key,
|
|
}
|
|
}
|
|
|
|
func alertMutex(err error) {
|
|
log.Print(err, string(debug.Stack()))
|
|
}
|
|
|
|
func checkMutex(state map[mutexKey]mutexValue, add mutexKey) {
|
|
for k := range state {
|
|
if add == k {
|
|
alertMutex(fmt.Errorf("re-entrant lock: state=%v add=%v", state, add))
|
|
}
|
|
}
|
|
|
|
switch add.Type {
|
|
case mutexKeyTypeHostInfo:
|
|
// Check for any other hostinfo keys:
|
|
for k := range state {
|
|
if k.Type == mutexKeyTypeHostInfo {
|
|
alertMutex(fmt.Errorf("grabbing hostinfo lock and already have a hostinfo lock: state=%v add=%v", state, add))
|
|
}
|
|
}
|
|
if _, ok := state[mutexKey{Type: mutexKeyTypeHostMap}]; ok {
|
|
alertMutex(fmt.Errorf("grabbing hostinfo lock and already have hostmap: state=%v add=%v", state, add))
|
|
}
|
|
if _, ok := state[mutexKey{Type: mutexKeyTypeHandshakeManager}]; ok {
|
|
alertMutex(fmt.Errorf("grabbing hostinfo lock and already have handshake-manager: state=%v add=%v", state, add))
|
|
}
|
|
// case mutexKeyTypeHandshakeManager:
|
|
// if _, ok := state[mutexKey{Type: mutexKeyTypeHostMap}]; ok {
|
|
// alertMutex(fmt.Errorf("grabbing handshake-manager lock and already have hostmap: state=%v add=%v", state, add))
|
|
// }
|
|
case mutexKeyTypeHostMap:
|
|
if _, ok := state[mutexKey{Type: mutexKeyTypeHandshakeManager}]; ok {
|
|
alertMutex(fmt.Errorf("grabbing hostmap lock and already have handshake-manager: state=%v add=%v", state, add))
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *syncRWMutex) Lock() {
|
|
m := threadLocal.Get().(map[mutexKey]mutexValue)
|
|
checkMutex(m, s.mutexKey)
|
|
v := mutexValue{}
|
|
_, v.file, v.line, _ = runtime.Caller(1)
|
|
m[s.mutexKey] = v
|
|
s.RWMutex.Lock()
|
|
}
|
|
|
|
func (s *syncRWMutex) Unlock() {
|
|
m := threadLocal.Get().(map[mutexKey]mutexValue)
|
|
delete(m, s.mutexKey)
|
|
s.RWMutex.Unlock()
|
|
}
|
|
|
|
func (s *syncRWMutex) RLock() {
|
|
m := threadLocal.Get().(map[mutexKey]mutexValue)
|
|
checkMutex(m, s.mutexKey)
|
|
v := mutexValue{}
|
|
_, v.file, v.line, _ = runtime.Caller(1)
|
|
m[s.mutexKey] = v
|
|
s.RWMutex.RLock()
|
|
}
|
|
|
|
func (s *syncRWMutex) RUnlock() {
|
|
m := threadLocal.Get().(map[mutexKey]mutexValue)
|
|
delete(m, s.mutexKey)
|
|
s.RWMutex.RUnlock()
|
|
}
|