Mercurial > hg > bitcoin
annotate src/sync.cpp @ 2646:4f37a9f05ca0 draft
Merge pull request #1354 from fanquake/master
Update Header Licenses
author | Pieter Wuille <pieter.wuille@gmail.com> |
---|---|
date | Sun, 20 May 2012 12:27:50 -0700 |
parents | 5909e915a086 98dbb2aa4f5a |
children | d6fbfce3fe40 |
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 |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
10 #ifdef DEBUG_LOCKORDER |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
11 // |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
12 // Early deadlock detection. |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
13 // Problem being solved: |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
14 // 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
|
15 // 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
|
16 // --> 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
|
17 // Solution implemented here: |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
18 // Keep track of pairs of locks: (A before B), (A before C), etc. |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
19 // Complain if any thread trys to lock in a different order. |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
20 // |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
21 |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
22 struct CLockLocation |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
23 { |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
24 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
|
25 { |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
26 mutexName = pszName; |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
27 sourceFile = pszFile; |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
28 sourceLine = nLine; |
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 |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
31 std::string ToString() const |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
32 { |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
33 return mutexName+" "+sourceFile+":"+itostr(sourceLine); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
34 } |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
35 |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
36 private: |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
37 std::string mutexName; |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
38 std::string sourceFile; |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
39 int sourceLine; |
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 |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
42 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
|
43 |
2610
5909e915a086
Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents:
2489
diff
changeset
|
44 static boost::mutex dd_mutex; |
2489
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
45 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
|
46 static boost::thread_specific_ptr<LockStack> lockstack; |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
47 |
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 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
|
50 { |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
51 printf("POTENTIAL DEADLOCK DETECTED\n"); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
52 printf("Previous lock order was:\n"); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
53 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
|
54 { |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
55 if (i.first == mismatch.first) printf(" (1)"); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
56 if (i.first == mismatch.second) printf(" (2)"); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
57 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
|
58 } |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
59 printf("Current lock order is:\n"); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
60 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
|
61 { |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
62 if (i.first == mismatch.first) printf(" (1)"); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
63 if (i.first == mismatch.second) printf(" (2)"); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
64 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
|
65 } |
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 |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
68 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
|
69 { |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
70 if (lockstack.get() == NULL) |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
71 lockstack.reset(new LockStack); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
72 |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
73 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
|
74 dd_mutex.lock(); |
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 (*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
|
77 |
2610
5909e915a086
Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents:
2489
diff
changeset
|
78 if (!fTry) { |
5909e915a086
Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents:
2489
diff
changeset
|
79 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
|
80 if (i.first == c) break; |
2489
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
81 |
2610
5909e915a086
Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents:
2489
diff
changeset
|
82 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
|
83 if (lockorders.count(p1)) |
5909e915a086
Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents:
2489
diff
changeset
|
84 continue; |
5909e915a086
Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents:
2489
diff
changeset
|
85 lockorders[p1] = (*lockstack); |
2489
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
86 |
2610
5909e915a086
Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents:
2489
diff
changeset
|
87 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
|
88 if (lockorders.count(p2)) |
5909e915a086
Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents:
2489
diff
changeset
|
89 { |
5909e915a086
Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents:
2489
diff
changeset
|
90 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
|
91 break; |
5909e915a086
Use boost::thread locking instead of interprocess
Pieter Wuille <pieter.wuille@gmail.com>
parents:
2489
diff
changeset
|
92 } |
2489
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
93 } |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
94 } |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
95 dd_mutex.unlock(); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
96 } |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
97 |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
98 static void pop_lock() |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
99 { |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
100 if (fDebug) |
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 const CLockLocation& locklocation = (*lockstack).rbegin()->second; |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
103 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
|
104 } |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
105 dd_mutex.lock(); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
106 (*lockstack).pop_back(); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
107 dd_mutex.unlock(); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
108 } |
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 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
|
111 { |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
112 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
|
113 } |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
114 |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
115 void LeaveCritical() |
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 pop_lock(); |
ae569fd652ef
Split synchronization mechanisms from util.{h,cpp}
Pieter Wuille <pieter.wuille@gmail.com>
parents:
diff
changeset
|
118 } |
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 #endif /* DEBUG_LOCKORDER */ |