]> Git Repo - VerusCoin.git/blame - src/sync.cpp
test
[VerusCoin.git] / src / sync.cpp
CommitLineData
f914f1a7 1// Copyright (c) 2011-2012 The Bitcoin Core developers
78253fcb 2// Distributed under the MIT software license, see the accompanying
3a25a2b9 3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
7f3ccb59
PW
4
5#include "sync.h"
51ed9ec9 6
660ff174 7#include "util.h"
d2d6f708 8#include "utilstrencodings.h"
7f3ccb59 9
611116d4
PK
10#include <stdio.h>
11
660ff174 12#include <boost/foreach.hpp>
d2d6f708 13#include <boost/thread.hpp>
7f3ccb59 14
4d009243
MC
15#ifdef DEBUG_LOCKCONTENTION
16void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
17{
881a85a2
GA
18 LogPrintf("LOCKCONTENTION: %s\n", pszName);
19 LogPrintf("Locker: %s:%d\n", pszFile, nLine);
4d009243
MC
20}
21#endif /* DEBUG_LOCKCONTENTION */
22
7f3ccb59
PW
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.
e7494052 32// Complain if any thread tries to lock in a different order.
7f3ccb59
PW
33//
34
20e01b1a 35struct CLockLocation {
7f3ccb59
PW
36 CLockLocation(const char* pszName, const char* pszFile, int nLine)
37 {
38 mutexName = pszName;
39 sourceFile = pszFile;
40 sourceLine = nLine;
41 }
42
43 std::string ToString() const
44 {
20e01b1a 45 return mutexName + " " + sourceFile + ":" + itostr(sourceLine);
7f3ccb59
PW
46 }
47
c649637b
GA
48 std::string MutexName() const { return mutexName; }
49
7f3ccb59
PW
50private:
51 std::string mutexName;
52 std::string sourceFile;
53 int sourceLine;
54};
55
20e01b1a 56typedef std::vector<std::pair<void*, CLockLocation> > LockStack;
7f3ccb59 57
660ff174 58static boost::mutex dd_mutex;
7f3ccb59
PW
59static std::map<std::pair<void*, void*>, LockStack> lockorders;
60static boost::thread_specific_ptr<LockStack> lockstack;
61
62
63static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
64{
881a85a2
GA
65 LogPrintf("POTENTIAL DEADLOCK DETECTED\n");
66 LogPrintf("Previous lock order was:\n");
20e01b1a
PW
67 BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s2) {
68 if (i.first == mismatch.first)
69 LogPrintf(" (1)");
70 if (i.first == mismatch.second)
71 LogPrintf(" (2)");
7d9d134b 72 LogPrintf(" %s\n", i.second.ToString());
7f3ccb59 73 }
881a85a2 74 LogPrintf("Current lock order is:\n");
20e01b1a
PW
75 BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s1) {
76 if (i.first == mismatch.first)
77 LogPrintf(" (1)");
78 if (i.first == mismatch.second)
79 LogPrintf(" (2)");
7d9d134b 80 LogPrintf(" %s\n", i.second.ToString());
7f3ccb59
PW
81 }
82}
83
84static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
85{
7f3ccb59
PW
86 if (lockstack.get() == NULL)
87 lockstack.reset(new LockStack);
88
7f3ccb59
PW
89 dd_mutex.lock();
90
91 (*lockstack).push_back(std::make_pair(c, locklocation));
92
660ff174 93 if (!fTry) {
20e01b1a
PW
94 BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, (*lockstack)) {
95 if (i.first == c)
96 break;
660ff174
PW
97
98 std::pair<void*, void*> p1 = std::make_pair(i.first, c);
99 if (lockorders.count(p1))
100 continue;
101 lockorders[p1] = (*lockstack);
102
103 std::pair<void*, void*> p2 = std::make_pair(c, i.first);
20e01b1a 104 if (lockorders.count(p2)) {
660ff174
PW
105 potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
106 break;
107 }
7f3ccb59
PW
108 }
109 }
110 dd_mutex.unlock();
111}
112
113static void pop_lock()
114{
7f3ccb59
PW
115 dd_mutex.lock();
116 (*lockstack).pop_back();
117 dd_mutex.unlock();
118}
119
120void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
121{
122 push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry);
123}
124
125void LeaveCritical()
126{
127 pop_lock();
128}
129
c649637b
GA
130std::string LocksHeld()
131{
132 std::string result;
20e01b1a 133 BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack)
c649637b
GA
134 result += i.second.ToString() + std::string("\n");
135 return result;
136}
137
20e01b1a 138void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
c649637b 139{
20e01b1a
PW
140 BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack)
141 if (i.first == cs)
142 return;
143 fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
ca4cf5cf 144 abort();
c649637b
GA
145}
146
7f3ccb59 147#endif /* DEBUG_LOCKORDER */
This page took 0.233758 seconds and 4 git commands to generate.