| 216 | template void EnterCritical(const char*, const char*, int, std::recursive_mutex*, bool); |
| 217 | |
| 218 | void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) |
| 219 | { |
| 220 | LockData& lockdata = GetLockData(); |
| 221 | std::lock_guard<std::mutex> lock(lockdata.dd_mutex); |
| 222 | |
| 223 | const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()]; |
| 224 | if (!lock_stack.empty()) { |
| 225 | const auto& lastlock = lock_stack.back(); |
| 226 | if (lastlock.first == cs) { |
| 227 | lockname = lastlock.second.Name(); |
| 228 | return; |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | LogPrintf("INCONSISTENT LOCK ORDER DETECTED\n"); |
| 233 | LogPrintf("Current lock order (least recent first) is:\n"); |
| 234 | for (const LockStackItem& i : lock_stack) { |
| 235 | LogPrintf(" %s\n", i.second.ToString()); |
| 236 | } |
| 237 | if (g_debug_lockorder_abort) { |
| 238 | tfm::format(std::cerr, "%s:%s %s was not most recent critical section locked, details in debug log.\n", file, line, guardname); |
| 239 | abort(); |
| 240 | } |
| 241 | throw std::logic_error(strprintf("%s was not most recent critical section locked", guardname)); |
| 242 | } |
| 243 | |
| 244 | void LeaveCritical() |
| 245 | { |