@@ -56,7 +56,7 @@ func (m *RWMutex) RUnlock() {
5656
5757var (
5858 globalMutex = new (sync.Mutex )
59- waitingList = make (map [int32 ]* waiting )
59+ waitingList = make (map [int32 ]* lockUsage )
6060 titleStr = []byte ("[DEAD LOCK]\n " )
6161 goStr = []byte ("goroutine " )
6262 waitStr = []byte (" wait" )
@@ -66,101 +66,105 @@ var (
6666 lineStr = []byte {'\n' }
6767)
6868
69- type waiting struct {
70- monitor * monitor
71- mode byte
72- holder int32
73- holderStack debug.StackInfo
69+ type lockUsage struct {
70+ monitor * monitor
71+ mode byte
72+ goid int32
73+ stack debug.StackInfo
7474}
7575
7676type monitor struct {
7777 holders * list.List
7878}
7979
80- func (m * monitor ) wait (mode byte ) * waiting {
80+ func (m * monitor ) wait (mode byte ) * lockUsage {
8181 globalMutex .Lock ()
8282 defer globalMutex .Unlock ()
8383
84- waitInfo := & waiting {m , mode , goid .Get (), debug .StackTrace (3 , 0 )}
85- waitingList [waitInfo .holder ] = waitInfo
84+ waitInfo := & lockUsage {m , mode , goid .Get (), debug .StackTrace (3 , 0 )}
85+ waitingList [waitInfo .goid ] = waitInfo
8686
8787 if m .holders == nil {
8888 m .holders = list .New ()
8989 }
9090
91- m .verify (mode , []* waiting {waitInfo })
91+ m .diagnose (mode , []* lockUsage {waitInfo })
9292
9393 return waitInfo
9494}
9595
96- func (m * monitor ) verify (mode byte , waitLink []* waiting ) {
96+ func (m * monitor ) diagnose (mode byte , waitLink []* lockUsage ) {
9797 for i := m .holders .Front (); i != nil ; i = i .Next () {
98- holder := i .Value .(* waiting )
98+ holder := i .Value .(* lockUsage )
9999 if mode != 'r' || holder .mode != 'r' {
100100 // deadlock detected
101- if holder .holder == waitLink [0 ].holder {
102- buf := new (bytes.Buffer )
103- buf .Write (titleStr )
104- for i := 0 ; i < len (waitLink ); i ++ {
105- buf .Write (goStr )
106- buf .WriteString (strconv .Itoa (int (waitLink [i ].holder )))
107- buf .Write (waitStr )
108- if waitLink [i ].mode == 'w' {
109- buf .Write (writeStr )
110- } else {
111- buf .Write (readStr )
112- }
113- buf .Write (lineStr )
114- buf .Write (waitLink [i ].holderStack .Bytes (" " ))
115-
116- // lookup waiting for who
117- n := i + 1
118- if n == len (waitLink ) {
119- n = 0
120- }
121- waitWho := waitLink [n ]
122-
123- for j := waitLink [i ].monitor .holders .Front (); j != nil ; j = j .Next () {
124- waitHolder := j .Value .(* waiting )
125- if waitHolder .holder == waitWho .holder {
126- buf .Write (goStr )
127- buf .WriteString (strconv .Itoa (int (waitHolder .holder )))
128- buf .Write (holdStr )
129- if waitHolder .mode == 'w' {
130- buf .Write (writeStr )
131- } else {
132- buf .Write (readStr )
133- }
134- buf .Write (lineStr )
135- buf .Write (waitHolder .holderStack .Bytes (" " ))
136- break
137- }
138- }
139- }
140- panic (DeadlockError (buf .String ()))
101+ if holder .goid == waitLink [0 ].goid {
102+ deadlockPanic (waitLink )
141103 }
142104 // the lock holder is waiting for another lock
143- if waitInfo , exists := waitingList [holder .holder ]; exists {
144- waitInfo .monitor .verify (waitInfo .mode , append (waitLink , waitInfo ))
105+ if waitInfo , exists := waitingList [holder .goid ]; exists {
106+ waitInfo .monitor .diagnose (waitInfo .mode , append (waitLink , waitInfo ))
145107 }
146108 }
147109 }
148110}
149111
150- func (m * monitor ) using (waitInfo * waiting ) {
112+ func (m * monitor ) using (waitInfo * lockUsage ) {
151113 globalMutex .Lock ()
152114 defer globalMutex .Unlock ()
153115
154- delete (waitingList , waitInfo .holder )
116+ delete (waitingList , waitInfo .goid )
155117 m .holders .PushBack (waitInfo )
156118}
157119
158120func (m * monitor ) release (mode byte ) {
159- holder := goid .Get ()
121+ id := goid .Get ()
160122 for i := m .holders .Back (); i != nil ; i = i .Prev () {
161- if info := i .Value .(* waiting ); info .holder == holder && info .mode == mode {
123+ if info := i .Value .(* lockUsage ); info .goid == id && info .mode == mode {
162124 m .holders .Remove (i )
163125 break
164126 }
165127 }
166128}
129+
130+ func deadlockPanic (waitLink []* lockUsage ) {
131+ buf := new (bytes.Buffer )
132+ buf .Write (titleStr )
133+ for i := 0 ; i < len (waitLink ); i ++ {
134+ buf .Write (goStr )
135+ buf .WriteString (strconv .Itoa (int (waitLink [i ].goid )))
136+ buf .Write (waitStr )
137+ if waitLink [i ].mode == 'w' {
138+ buf .Write (writeStr )
139+ } else {
140+ buf .Write (readStr )
141+ }
142+ buf .Write (lineStr )
143+ buf .Write (waitLink [i ].stack .Bytes (" " ))
144+
145+ // lookup waiting for who
146+ n := i + 1
147+ if n == len (waitLink ) {
148+ n = 0
149+ }
150+ waitWho := waitLink [n ]
151+
152+ for j := waitLink [i ].monitor .holders .Front (); j != nil ; j = j .Next () {
153+ waitHolder := j .Value .(* lockUsage )
154+ if waitHolder .goid == waitWho .goid {
155+ buf .Write (goStr )
156+ buf .WriteString (strconv .Itoa (int (waitHolder .goid )))
157+ buf .Write (holdStr )
158+ if waitHolder .mode == 'w' {
159+ buf .Write (writeStr )
160+ } else {
161+ buf .Write (readStr )
162+ }
163+ buf .Write (lineStr )
164+ buf .Write (waitHolder .stack .Bytes (" " ))
165+ break
166+ }
167+ }
168+ }
169+ panic (DeadlockError (buf .String ()))
170+ }
0 commit comments