12 #include <boost/foreach.hpp> 13 #include <boost/thread.hpp> 15 #ifdef DEBUG_LOCKCONTENTION 16 void PrintLockContention(
const char* pszName,
const char* pszFile,
int nLine)
18 LogPrintf(
"LOCKCONTENTION: %s Locker: %s:%d\n", pszName, pszFile, nLine);
22 #ifdef DEBUG_LOCKORDER 34 struct CLockLocation {
35 CLockLocation(
const char* pszName,
const char* pszFile,
int nLine,
bool fTryIn)
43 std::string ToString()
const 45 return mutexName +
" " + sourceFile +
":" +
itostr(sourceLine) + (fTry ?
" (TRY)" :
"");
48 std::string MutexName()
const {
return mutexName; }
52 std::string mutexName;
53 std::string sourceFile;
57 typedef std::vector<std::pair<void*, CLockLocation> > LockStack;
59 static boost::mutex dd_mutex;
60 static std::map<std::pair<void*, void*>, LockStack> lockorders;
61 static boost::thread_specific_ptr<LockStack> lockstack;
64 static void potential_deadlock_detected(
const std::pair<void*, void*>& mismatch,
const LockStack& s1,
const LockStack& s2)
72 bool firstLocked =
false;
73 bool secondLocked =
false;
74 bool onlyMaybeDeadlock =
false;
75 std::string strOutput =
"";
77 strOutput +=
"POTENTIAL DEADLOCK DETECTED\n";
78 strOutput +=
"Previous lock order was:\n";
79 BOOST_FOREACH (
const PAIRTYPE(
void*, CLockLocation) & i, s2) {
80 if (i.first == mismatch.first) {
82 if (!firstLocked && secondLocked && i.second.fTry)
83 onlyMaybeDeadlock =
true;
86 if (i.first == mismatch.second) {
88 if (!secondLocked && firstLocked && i.second.fTry)
89 onlyMaybeDeadlock =
true;
92 strOutput +=
strprintf(
" %s\n", i.second.ToString().c_str());
96 strOutput +=
"Current lock order is:\n";
97 BOOST_FOREACH (
const PAIRTYPE(
void*, CLockLocation) & i, s1) {
98 if (i.first == mismatch.first) {
100 if (!firstLocked && secondLocked && i.second.fTry)
101 onlyMaybeDeadlock =
true;
104 if (i.first == mismatch.second) {
106 if (!secondLocked && firstLocked && i.second.fTry)
107 onlyMaybeDeadlock =
true;
110 strOutput +=
strprintf(
" %s\n", i.second.ToString().c_str());
112 if(!onlyMaybeDeadlock) {
113 printf(
"%s\n", strOutput.c_str());
116 assert(onlyMaybeDeadlock);
119 static void push_lock(
void* c,
const CLockLocation& locklocation,
bool fTry)
121 if (lockstack.get() == NULL)
122 lockstack.reset(
new LockStack);
126 (*lockstack).push_back(std::make_pair(c, locklocation));
129 BOOST_FOREACH (
const PAIRTYPE(
void*, CLockLocation) & i, (*lockstack)) {
133 std::pair<void*, void*> p1 = std::make_pair(i.first, c);
134 if (lockorders.count(p1))
136 lockorders[p1] = (*lockstack);
138 std::pair<void*, void*> p2 = std::make_pair(c, i.first);
139 if (lockorders.count(p2))
140 potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
146 static void pop_lock()
149 (*lockstack).pop_back();
153 void EnterCritical(
const char* pszName,
const char* pszFile,
int nLine,
void* cs,
bool fTry)
155 push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry), fTry);
163 std::string LocksHeld()
166 BOOST_FOREACH (
const PAIRTYPE(
void*, CLockLocation) & i, *lockstack)
167 result += i.second.ToString() + std::string(
"\n");
173 BOOST_FOREACH (
const PAIRTYPE(
void*, CLockLocation) & i, *lockstack)
176 fprintf(
stderr,
"Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
static void AssertLockHeldInternal(const char *pszName, const char *pszFile, int nLine, void *cs)
static void EnterCritical(const char *pszName, const char *pszFile, int nLine, void *cs, bool fTry=false)
static void LeaveCritical()
std::string itostr(int n)