@@ -56,7 +56,7 @@ func (m *RWMutex) RUnlock() {
56
56
57
57
var (
58
58
globalMutex = new (sync.Mutex )
59
- waitingList = make (map [int32 ]* waiting )
59
+ waitingList = make (map [int32 ]* lockUsage )
60
60
titleStr = []byte ("[DEAD LOCK]\n " )
61
61
goStr = []byte ("goroutine " )
62
62
waitStr = []byte (" wait" )
@@ -66,101 +66,105 @@ var (
66
66
lineStr = []byte {'\n' }
67
67
)
68
68
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
74
74
}
75
75
76
76
type monitor struct {
77
77
holders * list.List
78
78
}
79
79
80
- func (m * monitor ) wait (mode byte ) * waiting {
80
+ func (m * monitor ) wait (mode byte ) * lockUsage {
81
81
globalMutex .Lock ()
82
82
defer globalMutex .Unlock ()
83
83
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
86
86
87
87
if m .holders == nil {
88
88
m .holders = list .New ()
89
89
}
90
90
91
- m .verify (mode , []* waiting {waitInfo })
91
+ m .diagnose (mode , []* lockUsage {waitInfo })
92
92
93
93
return waitInfo
94
94
}
95
95
96
- func (m * monitor ) verify (mode byte , waitLink []* waiting ) {
96
+ func (m * monitor ) diagnose (mode byte , waitLink []* lockUsage ) {
97
97
for i := m .holders .Front (); i != nil ; i = i .Next () {
98
- holder := i .Value .(* waiting )
98
+ holder := i .Value .(* lockUsage )
99
99
if mode != 'r' || holder .mode != 'r' {
100
100
// 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 )
141
103
}
142
104
// 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 ))
145
107
}
146
108
}
147
109
}
148
110
}
149
111
150
- func (m * monitor ) using (waitInfo * waiting ) {
112
+ func (m * monitor ) using (waitInfo * lockUsage ) {
151
113
globalMutex .Lock ()
152
114
defer globalMutex .Unlock ()
153
115
154
- delete (waitingList , waitInfo .holder )
116
+ delete (waitingList , waitInfo .goid )
155
117
m .holders .PushBack (waitInfo )
156
118
}
157
119
158
120
func (m * monitor ) release (mode byte ) {
159
- holder := goid .Get ()
121
+ id := goid .Get ()
160
122
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 {
162
124
m .holders .Remove (i )
163
125
break
164
126
}
165
127
}
166
128
}
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