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