Changeset View
Changeset View
Standalone View
Standalone View
src/sync.cpp
// Copyright (c) 2011-2016 The Bitcoin Core developers | // Copyright (c) 2011-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <sync.h> | #include <sync.h> | ||||
#include <logging.h> | #include <logging.h> | ||||
#include <util/strencodings.h> | #include <util/strencodings.h> | ||||
#include <util/threadnames.h> | |||||
#include <tinyformat.h> | |||||
#include <cstdio> | #include <cstdio> | ||||
#include <map> | #include <map> | ||||
#include <set> | #include <set> | ||||
#ifdef DEBUG_LOCKCONTENTION | #ifdef DEBUG_LOCKCONTENTION | ||||
void PrintLockContention(const char *pszName, const char *pszFile, int nLine) { | void PrintLockContention(const char *pszName, const char *pszFile, int nLine) { | ||||
LogPrintf("LOCKCONTENTION: %s\n", pszName); | LogPrintf("LOCKCONTENTION: %s\n", pszName); | ||||
Show All 11 Lines | |||||
// they run. | // they run. | ||||
// Solution implemented here: | // Solution implemented here: | ||||
// Keep track of pairs of locks: (A before B), (A before C), etc. | // Keep track of pairs of locks: (A before B), (A before C), etc. | ||||
// Complain if any thread tries to lock in a different order. | // Complain if any thread tries to lock in a different order. | ||||
// | // | ||||
struct CLockLocation { | struct CLockLocation { | ||||
CLockLocation(const char *pszName, const char *pszFile, int nLine, | CLockLocation(const char *pszName, const char *pszFile, int nLine, | ||||
bool fTryIn) { | bool fTryIn, const std::string &thread_name) | ||||
mutexName = pszName; | : fTry(fTryIn), mutexName(pszName), sourceFile(pszFile), | ||||
sourceFile = pszFile; | m_thread_name(thread_name), sourceLine(nLine) {} | ||||
sourceLine = nLine; | |||||
fTry = fTryIn; | |||||
} | |||||
std::string ToString() const { | std::string ToString() const { | ||||
return mutexName + " " + sourceFile + ":" + itostr(sourceLine) + | return tfm::format("%s %s:%s%s (in thread %s)", mutexName, sourceFile, | ||||
(fTry ? " (TRY)" : ""); | itostr(sourceLine), (fTry ? " (TRY)" : ""), | ||||
m_thread_name); | |||||
} | } | ||||
private: | private: | ||||
bool fTry; | bool fTry; | ||||
std::string mutexName; | std::string mutexName; | ||||
std::string sourceFile; | std::string sourceFile; | ||||
const std::string &m_thread_name; | |||||
int sourceLine; | int sourceLine; | ||||
}; | }; | ||||
typedef std::vector<std::pair<void *, CLockLocation>> LockStack; | typedef std::vector<std::pair<void *, CLockLocation>> LockStack; | ||||
typedef std::map<std::pair<void *, void *>, LockStack> LockOrders; | typedef std::map<std::pair<void *, void *>, LockStack> LockOrders; | ||||
typedef std::set<std::pair<void *, void *>> InvLockOrders; | typedef std::set<std::pair<void *, void *>> InvLockOrders; | ||||
struct LockData { | struct LockData { | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | for (const std::pair<void *, CLockLocation> &i : g_lockstack) { | ||||
if (i.first == c) { | if (i.first == c) { | ||||
break; | break; | ||||
} | } | ||||
std::pair<void *, void *> p1 = std::make_pair(i.first, c); | std::pair<void *, void *> p1 = std::make_pair(i.first, c); | ||||
if (lockdata.lockorders.count(p1)) { | if (lockdata.lockorders.count(p1)) { | ||||
continue; | continue; | ||||
} | } | ||||
lockdata.lockorders[p1] = g_lockstack; | lockdata.lockorders.emplace(p1, g_lockstack); | ||||
std::pair<void *, void *> p2 = std::make_pair(c, i.first); | std::pair<void *, void *> p2 = std::make_pair(c, i.first); | ||||
lockdata.invlockorders.insert(p2); | lockdata.invlockorders.insert(p2); | ||||
if (lockdata.lockorders.count(p2)) { | if (lockdata.lockorders.count(p2)) { | ||||
potential_deadlock_detected(p1, lockdata.lockorders[p2], | potential_deadlock_detected(p1, lockdata.lockorders[p2], | ||||
lockdata.lockorders[p1]); | lockdata.lockorders[p1]); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static void pop_lock() { | static void pop_lock() { | ||||
g_lockstack.pop_back(); | g_lockstack.pop_back(); | ||||
} | } | ||||
void EnterCritical(const char *pszName, const char *pszFile, int nLine, | void EnterCritical(const char *pszName, const char *pszFile, int nLine, | ||||
void *cs, bool fTry) { | void *cs, bool fTry) { | ||||
push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry)); | push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry, | ||||
util::ThreadGetInternalName())); | |||||
} | } | ||||
void LeaveCritical() { | void LeaveCritical() { | ||||
pop_lock(); | pop_lock(); | ||||
} | } | ||||
std::string LocksHeld() { | std::string LocksHeld() { | ||||
std::string result; | std::string result; | ||||
▲ Show 20 Lines • Show All 59 Lines • Show Last 20 Lines |