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
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
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 */