16
16
#include < map>
17
17
#include < set>
18
18
#include < system_error>
19
+ #include < thread>
20
+ #include < unordered_map>
19
21
#include < utility>
20
22
#include < vector>
21
23
@@ -77,12 +79,14 @@ struct CLockLocation {
77
79
78
80
using LockStackItem = std::pair<void *, CLockLocation>;
79
81
using LockStack = std::vector<LockStackItem>;
82
+ using LockStacks = std::unordered_map<std::thread::id, LockStack>;
80
83
81
84
using LockPair = std::pair<void *, void *>;
82
85
using LockOrders = std::map<LockPair, LockStack>;
83
86
using InvLockOrders = std::set<LockPair>;
84
87
85
88
struct LockData {
89
+ LockStacks m_lock_stacks;
86
90
LockOrders lockorders;
87
91
InvLockOrders invlockorders;
88
92
std::mutex dd_mutex;
@@ -95,8 +99,6 @@ LockData& GetLockData() {
95
99
return lock_data;
96
100
}
97
101
98
- static thread_local LockStack g_lockstack;
99
-
100
102
static void potential_deadlock_detected (const LockPair& mismatch, const LockStack& s1, const LockStack& s2)
101
103
{
102
104
LogPrintf (" POTENTIAL DEADLOCK DETECTED\n " );
@@ -132,16 +134,16 @@ static void push_lock(void* c, const CLockLocation& locklocation)
132
134
LockData& lockdata = GetLockData ();
133
135
std::lock_guard<std::mutex> lock (lockdata.dd_mutex );
134
136
135
- g_lockstack. push_back ( std::make_pair (c, locklocation)) ;
136
-
137
- for (const LockStackItem& i : g_lockstack ) {
137
+ LockStack& lock_stack = lockdata. m_lock_stacks [ std::this_thread::get_id ()] ;
138
+ lock_stack. emplace_back (c, locklocation);
139
+ for (const LockStackItem& i : lock_stack ) {
138
140
if (i.first == c)
139
141
break ;
140
142
141
143
const LockPair p1 = std::make_pair (i.first , c);
142
144
if (lockdata.lockorders .count (p1))
143
145
continue ;
144
- lockdata.lockorders .emplace (p1, g_lockstack );
146
+ lockdata.lockorders .emplace (p1, lock_stack );
145
147
146
148
const LockPair p2 = std::make_pair (c, i.first );
147
149
lockdata.invlockorders .insert (p2);
@@ -152,7 +154,14 @@ static void push_lock(void* c, const CLockLocation& locklocation)
152
154
153
155
static void pop_lock ()
154
156
{
155
- g_lockstack.pop_back ();
157
+ LockData& lockdata = GetLockData ();
158
+ std::lock_guard<std::mutex> lock (lockdata.dd_mutex );
159
+
160
+ LockStack& lock_stack = lockdata.m_lock_stacks [std::this_thread::get_id ()];
161
+ lock_stack.pop_back ();
162
+ if (lock_stack.empty ()) {
163
+ lockdata.m_lock_stacks .erase (std::this_thread::get_id ());
164
+ }
156
165
}
157
166
158
167
void EnterCritical (const char * pszName, const char * pszFile, int nLine, void * cs, bool fTry )
@@ -162,11 +171,17 @@ void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs
162
171
163
172
void CheckLastCritical (void * cs, std::string& lockname, const char * guardname, const char * file, int line)
164
173
{
165
- if (!g_lockstack.empty ()) {
166
- const auto & lastlock = g_lockstack.back ();
167
- if (lastlock.first == cs) {
168
- lockname = lastlock.second .Name ();
169
- return ;
174
+ {
175
+ LockData& lockdata = GetLockData ();
176
+ std::lock_guard<std::mutex> lock (lockdata.dd_mutex );
177
+
178
+ const LockStack& lock_stack = lockdata.m_lock_stacks [std::this_thread::get_id ()];
179
+ if (!lock_stack.empty ()) {
180
+ const auto & lastlock = lock_stack.back ();
181
+ if (lastlock.first == cs) {
182
+ lockname = lastlock.second .Name ();
183
+ return ;
184
+ }
170
185
}
171
186
}
172
187
throw std::system_error (EPERM, std::generic_category (), strprintf (" %s:%s %s was not most recent critical section locked" , file, line, guardname));
@@ -179,15 +194,23 @@ void LeaveCritical()
179
194
180
195
std::string LocksHeld ()
181
196
{
197
+ LockData& lockdata = GetLockData ();
198
+ std::lock_guard<std::mutex> lock (lockdata.dd_mutex );
199
+
200
+ const LockStack& lock_stack = lockdata.m_lock_stacks [std::this_thread::get_id ()];
182
201
std::string result;
183
- for (const LockStackItem& i : g_lockstack )
202
+ for (const LockStackItem& i : lock_stack )
184
203
result += i.second .ToString () + std::string (" \n " );
185
204
return result;
186
205
}
187
206
188
207
static bool LockHeld (void * mutex)
189
208
{
190
- for (const LockStackItem& i : g_lockstack) {
209
+ LockData& lockdata = GetLockData ();
210
+ std::lock_guard<std::mutex> lock (lockdata.dd_mutex );
211
+
212
+ const LockStack& lock_stack = lockdata.m_lock_stacks [std::this_thread::get_id ()];
213
+ for (const LockStackItem& i : lock_stack) {
191
214
if (i.first == mutex) return true ;
192
215
}
193
216
0 commit comments