mutex_debug.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. //go:build mutex_debug
  2. // +build mutex_debug
  3. package nebula
  4. import (
  5. "strings"
  6. "sync"
  7. "github.com/timandy/routine"
  8. )
  9. var threadLocal routine.ThreadLocal = routine.NewThreadLocalWithInitial(func() any { return map[string]bool{} })
  10. type syncRWMutex struct {
  11. sync.RWMutex
  12. mutexType string
  13. }
  14. func newSyncRWMutex(t ...string) syncRWMutex {
  15. return syncRWMutex{
  16. mutexType: strings.Join(t, "-"),
  17. }
  18. }
  19. func checkMutex(state map[string]bool, add string) {
  20. if add == "hostinfo" {
  21. if state["hostmap-main"] {
  22. panic("grabbing hostinfo lock and already have hostmap-main")
  23. }
  24. if state["hostmap-pending"] {
  25. panic("grabbing hostinfo lock and already have hostmap-pending")
  26. }
  27. }
  28. if add == "hostmap-pending" {
  29. if state["hostmap-main"] {
  30. panic("grabbing hostmap-pending lock and already have hostmap-main")
  31. }
  32. }
  33. }
  34. func (s *syncRWMutex) Lock() {
  35. m := threadLocal.Get().(map[string]bool)
  36. checkMutex(m, s.mutexType)
  37. m[s.mutexType] = true
  38. s.RWMutex.Lock()
  39. }
  40. func (s *syncRWMutex) Unlock() {
  41. m := threadLocal.Get().(map[string]bool)
  42. m[s.mutexType] = false
  43. s.RWMutex.Unlock()
  44. }
  45. func (s *syncRWMutex) RLock() {
  46. m := threadLocal.Get().(map[string]bool)
  47. checkMutex(m, s.mutexType)
  48. m[s.mutexType] = true
  49. s.RWMutex.RLock()
  50. }
  51. func (s *syncRWMutex) RUnlock() {
  52. m := threadLocal.Get().(map[string]bool)
  53. m[s.mutexType] = false
  54. s.RWMutex.RUnlock()
  55. }