@@ -14,18 +14,18 @@ import (
1414)
1515
1616type Mutex struct {
17- mutexInfo
17+ mointor
1818 sync.Mutex
1919}
2020
2121func (m * Mutex ) Lock () {
22- holder , elem := m .mutexInfo .wait ()
22+ holder , elem := m .mointor .wait ()
2323 m .Mutex .Lock ()
24- m .mutexInfo .using (holder , elem )
24+ m .mointor .using (holder , elem )
2525}
2626
2727func (m * Mutex ) Unlock () {
28- m .mutexInfo .release ()
28+ m .mointor .release ()
2929 m .Mutex .Unlock ()
3030}
3131
@@ -50,73 +50,75 @@ func (rw *RWMutex) RUnlock() {
5050}
5151
5252var (
53- lockMutex = new (sync.Mutex )
54- waitTargets = make (map [int32 ]* mutexInfo )
53+ globalMutex = new (sync.Mutex )
54+ waitTargets = make (map [int32 ]* mointor )
5555 goroutineBegin = []byte ("goroutine " )
5656 goroutineEnd = []byte ("\n \n " )
5757)
5858
59- func goroutine (id int32 , stack []byte ) []byte {
60- head := append (strconv .AppendInt (goroutineBegin , int64 (id ), 10 ), ' ' )
61- begin := bytes .Index (stack , head )
62- end := bytes .Index (stack [begin :], goroutineEnd )
63- if end == - 1 {
64- end = len (stack ) - begin
65- }
66- return stack [begin : begin + end ]
67- }
68-
69- type mutexInfo struct {
59+ type mointor struct {
7060 holder int32
7161 waiting * list.List
7262}
7363
74- func (lock * mutexInfo ) wait () (int32 , * list.Element ) {
75- lockMutex .Lock ()
76- defer lockMutex .Unlock ()
64+ func (m * mointor ) wait () (int32 , * list.Element ) {
65+ globalMutex .Lock ()
66+ defer globalMutex .Unlock ()
7767
7868 holder := goid .Get ()
79- waitTargets [holder ] = lock
69+ waitTargets [holder ] = m
8070
81- if lock .waiting == nil {
82- lock .waiting = list .New ()
71+ if m .waiting == nil {
72+ m .waiting = list .New ()
8373 }
8474
85- lock .verify (holder , []* mutexInfo { lock })
86- return holder , lock .waiting .PushBack (holder )
75+ m .verify (holder , []int32 { holder })
76+ return holder , m .waiting .PushBack (holder )
8777}
8878
89- func (lock * mutexInfo ) verify (holder int32 , link []* mutexInfo ) {
90- if lock .holder != 0 {
91- if lock .holder == holder {
79+ func (m * mointor ) verify (holder int32 , holderLink []int32 ) {
80+ if m .holder != 0 {
81+ if m .holder == holder {
82+ buf := new (bytes.Buffer )
83+ fmt .Fprintln (buf , "[DEAD LOCK]\n " )
84+
85+ // dump goroutines
9286 stackBuf := new (bytes.Buffer )
9387 prof := pprof .Lookup ("goroutine" )
9488 prof .WriteTo (stackBuf , 2 )
9589 stack := stackBuf .Bytes ()
96-
97- buf := new (bytes.Buffer )
98- fmt .Fprintln (buf , "[DEAD LOCK]\n " )
99- fmt .Fprintf (buf , "%s\n \n " , goroutine (holder , stack ))
100- for i := 0 ; i < len (link ); i ++ {
101- fmt .Fprintf (buf , "%s\n \n " , goroutine (link [i ].holder , stack ))
90+ fmt .Fprintf (buf , "%s\n \n " , traceGoroutine (holder , stack ))
91+ for i := 0 ; i < len (holderLink ); i ++ {
92+ fmt .Fprintf (buf , "%s\n \n " , traceGoroutine (holderLink [i ], stack ))
10293 }
94+
10395 panic (buf .String ())
10496 }
105- if waitTarget , exists := waitTargets [lock .holder ]; exists {
106- waitTarget .verify (holder , append (link , waitTarget ))
97+ if waitTarget , exists := waitTargets [m .holder ]; exists {
98+ waitTarget .verify (holder , append (holderLink , waitTarget . holder ))
10799 }
108100 }
109101}
110102
111- func (lock * mutexInfo ) using (holder int32 , elem * list.Element ) {
112- lockMutex .Lock ()
113- defer lockMutex .Unlock ()
103+ func (m * mointor ) using (holder int32 , elem * list.Element ) {
104+ globalMutex .Lock ()
105+ defer globalMutex .Unlock ()
114106
115107 delete (waitTargets , holder )
116- atomic .StoreInt32 (& lock .holder , holder )
117- lock .waiting .Remove (elem )
108+ atomic .StoreInt32 (& m .holder , holder )
109+ m .waiting .Remove (elem )
118110}
119111
120- func (lock * mutexInfo ) release () {
121- atomic .StoreInt32 (& lock .holder , 0 )
112+ func (m * mointor ) release () {
113+ atomic .StoreInt32 (& m .holder , 0 )
114+ }
115+
116+ func traceGoroutine (id int32 , stack []byte ) []byte {
117+ head := append (strconv .AppendInt (goroutineBegin , int64 (id ), 10 ), ' ' )
118+ begin := bytes .Index (stack , head )
119+ end := bytes .Index (stack [begin :], goroutineEnd )
120+ if end == - 1 {
121+ end = len (stack ) - begin
122+ }
123+ return stack [begin : begin + end ]
122124}
0 commit comments