annotate src/sync.cpp @ 3633:94f6e3e0c600 draft

Merge pull request #1880 from sipa/threadimport Move external block import to separate thread
author Jeff Garzik <jgarzik@exmulti.com>
date Sat, 20 Oct 2012 13:36:36 -0700
parents ea8bd30bedcb
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2489
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
1 // Copyright (c) 2011-2012 The Bitcoin developers
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
2 // Distributed under the MIT/X11 software license, see the accompanying
2607
98dbb2aa4f5a Update License in File Headers
Fordy <fanquake@gmail.com>
parents: 2489
diff changeset
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
2489
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
4
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
5 #include "sync.h"
2610
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
6 #include "util.h"
2489
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
7
2610
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
8 #include <boost/foreach.hpp>
2489
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
9
2728
d6fbfce3fe40 Fix DEBUG_LOCKCONTENTION
Matt Corallo <matt@bluematt.me>
parents: 2646
diff changeset
10 #ifdef DEBUG_LOCKCONTENTION
d6fbfce3fe40 Fix DEBUG_LOCKCONTENTION
Matt Corallo <matt@bluematt.me>
parents: 2646
diff changeset
11 void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
d6fbfce3fe40 Fix DEBUG_LOCKCONTENTION
Matt Corallo <matt@bluematt.me>
parents: 2646
diff changeset
12 {
d6fbfce3fe40 Fix DEBUG_LOCKCONTENTION
Matt Corallo <matt@bluematt.me>
parents: 2646
diff changeset
13 printf("LOCKCONTENTION: %s\n", pszName);
d6fbfce3fe40 Fix DEBUG_LOCKCONTENTION
Matt Corallo <matt@bluematt.me>
parents: 2646
diff changeset
14 printf("Locker: %s:%d\n", pszFile, nLine);
d6fbfce3fe40 Fix DEBUG_LOCKCONTENTION
Matt Corallo <matt@bluematt.me>
parents: 2646
diff changeset
15 }
d6fbfce3fe40 Fix DEBUG_LOCKCONTENTION
Matt Corallo <matt@bluematt.me>
parents: 2646
diff changeset
16 #endif /* DEBUG_LOCKCONTENTION */
d6fbfce3fe40 Fix DEBUG_LOCKCONTENTION
Matt Corallo <matt@bluematt.me>
parents: 2646
diff changeset
17
2489
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
18 #ifdef DEBUG_LOCKORDER
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
19 //
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
20 // Early deadlock detection.
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
21 // Problem being solved:
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
22 // Thread 1 locks A, then B, then C
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
23 // Thread 2 locks D, then C, then A
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
24 // --> may result in deadlock between the two threads, depending on when they run.
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
25 // Solution implemented here:
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
26 // Keep track of pairs of locks: (A before B), (A before C), etc.
3118
cd11cd29758b Fix a few typos
fanquake <fanquake@gmail.com>
parents: 2728
diff changeset
27 // Complain if any thread tries to lock in a different order.
2489
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
28 //
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
29
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
30 struct CLockLocation
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
31 {
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
32 CLockLocation(const char* pszName, const char* pszFile, int nLine)
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
33 {
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
34 mutexName = pszName;
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
35 sourceFile = pszFile;
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
36 sourceLine = nLine;
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
37 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
38
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
39 std::string ToString() const
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
40 {
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
41 return mutexName+" "+sourceFile+":"+itostr(sourceLine);
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
42 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
43
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
44 private:
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
45 std::string mutexName;
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
46 std::string sourceFile;
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
47 int sourceLine;
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
48 };
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
49
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
50 typedef std::vector< std::pair<void*, CLockLocation> > LockStack;
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
51
2610
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
52 static boost::mutex dd_mutex;
2489
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
53 static std::map<std::pair<void*, void*>, LockStack> lockorders;
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
54 static boost::thread_specific_ptr<LockStack> lockstack;
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
55
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
56
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
57 static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
58 {
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
59 printf("POTENTIAL DEADLOCK DETECTED\n");
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
60 printf("Previous lock order was:\n");
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
61 BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2)
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
62 {
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
63 if (i.first == mismatch.first) printf(" (1)");
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
64 if (i.first == mismatch.second) printf(" (2)");
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
65 printf(" %s\n", i.second.ToString().c_str());
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
66 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
67 printf("Current lock order is:\n");
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
68 BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1)
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
69 {
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
70 if (i.first == mismatch.first) printf(" (1)");
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
71 if (i.first == mismatch.second) printf(" (2)");
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
72 printf(" %s\n", i.second.ToString().c_str());
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
73 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
74 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
75
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
76 static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
77 {
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
78 if (lockstack.get() == NULL)
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
79 lockstack.reset(new LockStack);
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
80
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
81 if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str());
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
82 dd_mutex.lock();
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
83
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
84 (*lockstack).push_back(std::make_pair(c, locklocation));
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
85
2610
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
86 if (!fTry) {
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
87 BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack)) {
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
88 if (i.first == c) break;
2489
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
89
2610
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
90 std::pair<void*, void*> p1 = std::make_pair(i.first, c);
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
91 if (lockorders.count(p1))
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
92 continue;
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
93 lockorders[p1] = (*lockstack);
2489
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
94
2610
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
95 std::pair<void*, void*> p2 = std::make_pair(c, i.first);
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
96 if (lockorders.count(p2))
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
97 {
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
98 potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
99 break;
5909e915a086 Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents: 2489
diff changeset
100 }
2489
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
101 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
102 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
103 dd_mutex.unlock();
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
104 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
105
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
106 static void pop_lock()
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
107 {
3516
ea8bd30bedcb Trim trailing whitespace for src/*.{h,cpp}
Jeff Garzik <jgarzik@exmulti.com>
parents: 3118
diff changeset
108 if (fDebug)
2489
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
109 {
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
110 const CLockLocation& locklocation = (*lockstack).rbegin()->second;
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
111 printf("Unlocked: %s\n", locklocation.ToString().c_str());
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
112 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
113 dd_mutex.lock();
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
114 (*lockstack).pop_back();
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
115 dd_mutex.unlock();
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
116 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
117
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
118 void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
119 {
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
120 push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry);
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
121 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
122
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
123 void LeaveCritical()
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
124 {
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
125 pop_lock();
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
126 }
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
127
ae569fd652ef Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff changeset
128 #endif /* DEBUG_LOCKORDER */