diff options
Diffstat (limited to 'src/sync.cpp')
| -rw-r--r-- | src/sync.cpp | 83 |
1 files changed, 51 insertions, 32 deletions
diff --git a/src/sync.cpp b/src/sync.cpp index dbd9ebdae..a42293996 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -1,17 +1,22 @@ -// Copyright (c) 2011-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2011-2012 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "sync.h" + #include "util.h" +#include "utilstrencodings.h" + +#include <stdio.h> #include <boost/foreach.hpp> +#include <boost/thread.hpp> #ifdef DEBUG_LOCKCONTENTION void PrintLockContention(const char* pszName, const char* pszFile, int nLine) { - printf("LOCKCONTENTION: %s\n", pszName); - printf("Locker: %s:%d\n", pszFile, nLine); + LogPrintf("LOCKCONTENTION: %s\n", pszName); + LogPrintf("Locker: %s:%d\n", pszFile, nLine); } #endif /* DEBUG_LOCKCONTENTION */ @@ -24,11 +29,10 @@ void PrintLockContention(const char* pszName, const char* pszFile, int nLine) // --> may result in deadlock between the two threads, depending on when they run. // Solution implemented here: // Keep track of pairs of locks: (A before B), (A before C), etc. -// Complain if any thread trys 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) { mutexName = pszName; @@ -38,16 +42,18 @@ struct CLockLocation std::string ToString() const { - return mutexName+" "+sourceFile+":"+itostr(sourceLine); + return mutexName + " " + sourceFile + ":" + itostr(sourceLine); } + std::string MutexName() const { return mutexName; } + private: std::string mutexName; std::string sourceFile; int sourceLine; }; -typedef std::vector< std::pair<void*, CLockLocation> > LockStack; +typedef std::vector<std::pair<void*, CLockLocation> > LockStack; static boost::mutex dd_mutex; static std::map<std::pair<void*, void*>, LockStack> lockorders; @@ -56,20 +62,22 @@ static boost::thread_specific_ptr<LockStack> lockstack; static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2) { - printf("POTENTIAL DEADLOCK DETECTED\n"); - printf("Previous lock order was:\n"); - BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2) - { - if (i.first == mismatch.first) printf(" (1)"); - if (i.first == mismatch.second) printf(" (2)"); - printf(" %s\n", i.second.ToString().c_str()); + LogPrintf("POTENTIAL DEADLOCK DETECTED\n"); + LogPrintf("Previous lock order was:\n"); + BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s2) { + if (i.first == mismatch.first) + LogPrintf(" (1)"); + if (i.first == mismatch.second) + LogPrintf(" (2)"); + LogPrintf(" %s\n", i.second.ToString()); } - printf("Current lock order is:\n"); - BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1) - { - if (i.first == mismatch.first) printf(" (1)"); - if (i.first == mismatch.second) printf(" (2)"); - printf(" %s\n", i.second.ToString().c_str()); + LogPrintf("Current lock order is:\n"); + BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s1) { + if (i.first == mismatch.first) + LogPrintf(" (1)"); + if (i.first == mismatch.second) + LogPrintf(" (2)"); + LogPrintf(" %s\n", i.second.ToString()); } } @@ -78,14 +86,14 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) if (lockstack.get() == NULL) lockstack.reset(new LockStack); - if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str()); dd_mutex.lock(); (*lockstack).push_back(std::make_pair(c, locklocation)); if (!fTry) { - BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack)) { - if (i.first == c) break; + BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, (*lockstack)) { + if (i.first == c) + break; std::pair<void*, void*> p1 = std::make_pair(i.first, c); if (lockorders.count(p1)) @@ -93,8 +101,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) lockorders[p1] = (*lockstack); std::pair<void*, void*> p2 = std::make_pair(c, i.first); - if (lockorders.count(p2)) - { + if (lockorders.count(p2)) { potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]); break; } @@ -105,11 +112,6 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) static void pop_lock() { - if (fDebug) - { - const CLockLocation& locklocation = (*lockstack).rbegin()->second; - printf("Unlocked: %s\n", locklocation.ToString().c_str()); - } dd_mutex.lock(); (*lockstack).pop_back(); dd_mutex.unlock(); @@ -125,4 +127,21 @@ void LeaveCritical() pop_lock(); } +std::string LocksHeld() +{ + std::string result; + BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack) + result += i.second.ToString() + std::string("\n"); + return result; +} + +void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) +{ + BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack) + if (i.first == cs) + return; + fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str()); + abort(); +} + #endif /* DEBUG_LOCKORDER */ |