Master Core  v0.0.9 - 2abfd2849db8ba7a83957c64eb976b406713c123
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
sync.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2012 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "sync.h"
6 
7 #include "util.h"
8 
9 #include <boost/foreach.hpp>
10 
11 #ifdef DEBUG_LOCKCONTENTION
12 void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
13 {
14  LogPrintf("LOCKCONTENTION: %s\n", pszName);
15  LogPrintf("Locker: %s:%d\n", pszFile, nLine);
16 }
17 #endif /* DEBUG_LOCKCONTENTION */
18 
19 #ifdef DEBUG_LOCKORDER
20 //
21 // Early deadlock detection.
22 // Problem being solved:
23 // Thread 1 locks A, then B, then C
24 // Thread 2 locks D, then C, then A
25 // --> may result in deadlock between the two threads, depending on when they run.
26 // Solution implemented here:
27 // Keep track of pairs of locks: (A before B), (A before C), etc.
28 // Complain if any thread tries to lock in a different order.
29 //
30 
31 struct CLockLocation
32 {
33  CLockLocation(const char* pszName, const char* pszFile, int nLine)
34  {
35  mutexName = pszName;
36  sourceFile = pszFile;
37  sourceLine = nLine;
38  }
39 
40  std::string ToString() const
41  {
42  return mutexName+" "+sourceFile+":"+itostr(sourceLine);
43  }
44 
45  std::string MutexName() const { return mutexName; }
46 
47 private:
48  std::string mutexName;
49  std::string sourceFile;
50  int sourceLine;
51 };
52 
53 typedef std::vector< std::pair<void*, CLockLocation> > LockStack;
54 
55 static boost::mutex dd_mutex;
56 static std::map<std::pair<void*, void*>, LockStack> lockorders;
57 static boost::thread_specific_ptr<LockStack> lockstack;
58 
59 
60 static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
61 {
62  LogPrintf("POTENTIAL DEADLOCK DETECTED\n");
63  LogPrintf("Previous lock order was:\n");
64  BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2)
65  {
66  if (i.first == mismatch.first) LogPrintf(" (1)");
67  if (i.first == mismatch.second) LogPrintf(" (2)");
68  LogPrintf(" %s\n", i.second.ToString());
69  }
70  LogPrintf("Current lock order is:\n");
71  BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1)
72  {
73  if (i.first == mismatch.first) LogPrintf(" (1)");
74  if (i.first == mismatch.second) LogPrintf(" (2)");
75  LogPrintf(" %s\n", i.second.ToString());
76  }
77 }
78 
79 static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
80 {
81  if (lockstack.get() == NULL)
82  lockstack.reset(new LockStack);
83 
84  LogPrint("lock", "Locking: %s\n", locklocation.ToString());
85  dd_mutex.lock();
86 
87  (*lockstack).push_back(std::make_pair(c, locklocation));
88 
89  if (!fTry) {
90  BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack)) {
91  if (i.first == c) break;
92 
93  std::pair<void*, void*> p1 = std::make_pair(i.first, c);
94  if (lockorders.count(p1))
95  continue;
96  lockorders[p1] = (*lockstack);
97 
98  std::pair<void*, void*> p2 = std::make_pair(c, i.first);
99  if (lockorders.count(p2))
100  {
101  potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
102  break;
103  }
104  }
105  }
106  dd_mutex.unlock();
107 }
108 
109 static void pop_lock()
110 {
111  if (fDebug)
112  {
113  const CLockLocation& locklocation = (*lockstack).rbegin()->second;
114  LogPrint("lock", "Unlocked: %s\n", locklocation.ToString());
115  }
116  dd_mutex.lock();
117  (*lockstack).pop_back();
118  dd_mutex.unlock();
119 }
120 
121 void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
122 {
123  push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry);
124 }
125 
126 void LeaveCritical()
127 {
128  pop_lock();
129 }
130 
131 std::string LocksHeld()
132 {
133  std::string result;
134  BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)&i, *lockstack)
135  result += i.second.ToString() + std::string("\n");
136  return result;
137 }
138 
139 void AssertLockHeldInternal(const char *pszName, const char* pszFile, int nLine, void *cs)
140 {
141  BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)&i, *lockstack)
142  if (i.first == cs) return;
143  fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s",
144  pszName, pszFile, nLine, LocksHeld().c_str());
145  abort();
146 }
147 
148 #endif /* DEBUG_LOCKORDER */
bool fDebug
Definition: util.cpp:91
#define PAIRTYPE(t1, t2)
Definition: util.h:48
STL namespace.
#define LogPrintf(...)
Definition: util.h:117
static int LogPrint(const char *category, const char *format)
Definition: util.h:143
std::string itostr(int n)
Definition: util.h:219
static void AssertLockHeldInternal(const char *pszName, const char *pszFile, int nLine, void *cs)
Definition: sync.h:95
static void EnterCritical(const char *pszName, const char *pszFile, int nLine, void *cs, bool fTry=false)
Definition: sync.h:93
static void LeaveCritical()
Definition: sync.h:94