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