Mercurial > hg > bitcoin
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 |
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 | 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 | 10 #ifdef DEBUG_LOCKCONTENTION |
11 void PrintLockContention(const char* pszName, const char* pszFile, int nLine) | |
12 { | |
13 printf("LOCKCONTENTION: %s\n", pszName); | |
14 printf("Locker: %s:%d\n", pszFile, nLine); | |
15 } | |
16 #endif /* DEBUG_LOCKCONTENTION */ | |
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 | 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 */ |