Added
Link Here
|
1 |
rec: Add support for boost::context >= 1.61 |
2 |
|
3 |
https://github.com/PowerDNS/pdns/commits/master/pdns/mtasker_fcontext.cc |
4 |
|
5 |
--- mtasker_fcontext.cc.orig 2016-09-06 12:50:29 UTC |
6 |
+++ mtasker_fcontext.cc |
7 |
@@ -23,14 +23,15 @@ |
8 |
#include <exception> |
9 |
#include <cassert> |
10 |
#include <type_traits> |
11 |
-#if BOOST_VERSION > 106100 |
12 |
-#include <boost/context/detail/fcontext.hpp> |
13 |
-#else |
14 |
-#include <boost/context/fcontext.hpp> |
15 |
-#endif |
16 |
#include <boost/version.hpp> |
17 |
- |
18 |
+#if BOOST_VERSION < 106100 |
19 |
+#include <boost/context/fcontext.hpp> |
20 |
using boost::context::make_fcontext; |
21 |
+#else |
22 |
+#include <boost/context/detail/fcontext.hpp> |
23 |
+using boost::context::detail::make_fcontext; |
24 |
+#endif /* BOOST_VERSION < 106100 */ |
25 |
+ |
26 |
|
27 |
#if BOOST_VERSION < 105600 |
28 |
/* Note: This typedef means functions taking fcontext_t*, like jump_fcontext(), |
29 |
@@ -61,8 +62,15 @@ jump_fcontext (fcontext_t* const ofc, fc |
30 |
} |
31 |
} |
32 |
#else |
33 |
+ |
34 |
+#if BOOST_VERSION < 106100 |
35 |
using boost::context::fcontext_t; |
36 |
using boost::context::jump_fcontext; |
37 |
+#else |
38 |
+using boost::context::detail::fcontext_t; |
39 |
+using boost::context::detail::jump_fcontext; |
40 |
+using boost::context::detail::transfer_t; |
41 |
+#endif /* BOOST_VERSION < 106100 */ |
42 |
|
43 |
static_assert (std::is_pointer<fcontext_t>::value, |
44 |
"Boost Context has changed the fcontext_t type again :-("); |
45 |
@@ -72,7 +80,9 @@ static_assert (std::is_pointer<fcontext_ |
46 |
* jump. args_t simply provides a way to pass more by reference. |
47 |
*/ |
48 |
struct args_t { |
49 |
+#if BOOST_VERSION < 106100 |
50 |
fcontext_t prev_ctx = nullptr; |
51 |
+#endif |
52 |
pdns_ucontext_t* self = nullptr; |
53 |
boost::function<void(void)>* work = nullptr; |
54 |
}; |
55 |
@@ -80,7 +90,11 @@ struct args_t { |
56 |
extern "C" { |
57 |
static |
58 |
void |
59 |
+#if BOOST_VERSION < 106100 |
60 |
threadWrapper (intptr_t const xargs) { |
61 |
+#else |
62 |
+threadWrapper (transfer_t const t) { |
63 |
+#endif |
64 |
/* Access the args passed from pdns_makecontext, and copy them directly from |
65 |
* the calling stack on to ours (we're now using the MThreads stack). |
66 |
* This saves heap allocating an args object, at the cost of an extra |
67 |
@@ -90,11 +104,28 @@ threadWrapper (intptr_t const xargs) { |
68 |
* the behaviour of the System V implementation, which can inherently only |
69 |
* be passed ints and pointers. |
70 |
*/ |
71 |
+#if BOOST_VERSION < 106100 |
72 |
auto args = reinterpret_cast<args_t*>(xargs); |
73 |
+#else |
74 |
+ auto args = reinterpret_cast<args_t*>(t.data); |
75 |
+#endif |
76 |
auto ctx = args->self; |
77 |
auto work = args->work; |
78 |
+ /* we switch back to pdns_makecontext() */ |
79 |
+#if BOOST_VERSION < 106100 |
80 |
jump_fcontext (reinterpret_cast<fcontext_t*>(&ctx->uc_mcontext), |
81 |
static_cast<fcontext_t>(args->prev_ctx), 0); |
82 |
+#else |
83 |
+ transfer_t res = jump_fcontext (t.fctx, 0); |
84 |
+ /* we got switched back from pdns_swapcontext() */ |
85 |
+ if (res.data) { |
86 |
+ /* if res.data is not a nullptr, it holds a pointer to the context |
87 |
+ we just switched from, and we need to fill it to be able to |
88 |
+ switch back to it later. */ |
89 |
+ fcontext_t* ptr = static_cast<fcontext_t*>(res.data); |
90 |
+ *ptr = res.fctx; |
91 |
+ } |
92 |
+#endif |
93 |
args = nullptr; |
94 |
|
95 |
try { |
96 |
@@ -106,9 +137,14 @@ threadWrapper (intptr_t const xargs) { |
97 |
|
98 |
/* Emulate the System V uc_link feature. */ |
99 |
auto const next_ctx = ctx->uc_link->uc_mcontext; |
100 |
+#if BOOST_VERSION < 106100 |
101 |
jump_fcontext (reinterpret_cast<fcontext_t*>(&ctx->uc_mcontext), |
102 |
static_cast<fcontext_t>(next_ctx), |
103 |
static_cast<bool>(ctx->exception)); |
104 |
+#else |
105 |
+ jump_fcontext (static_cast<fcontext_t>(next_ctx), 0); |
106 |
+#endif |
107 |
+ |
108 |
#ifdef NDEBUG |
109 |
__builtin_unreachable(); |
110 |
#endif |
111 |
@@ -129,10 +165,27 @@ pdns_ucontext_t::~pdns_ucontext_t |
112 |
void |
113 |
pdns_swapcontext |
114 |
(pdns_ucontext_t& __restrict octx, pdns_ucontext_t const& __restrict ctx) { |
115 |
+ /* we either switch back to threadwrapper() if it's the first time, |
116 |
+ or we switch back to pdns_swapcontext(), |
117 |
+ in both case we will be returning from a call to jump_fcontext(). */ |
118 |
+#if BOOST_VERSION < 106100 |
119 |
if (jump_fcontext (reinterpret_cast<fcontext_t*>(&octx.uc_mcontext), |
120 |
static_cast<fcontext_t>(ctx.uc_mcontext), 0)) { |
121 |
std::rethrow_exception (ctx.exception); |
122 |
} |
123 |
+#else |
124 |
+ transfer_t res = jump_fcontext (static_cast<fcontext_t>(ctx.uc_mcontext), &octx.uc_mcontext); |
125 |
+ if (res.data) { |
126 |
+ /* if res.data is not a nullptr, it holds a pointer to the context |
127 |
+ we just switched from, and we need to fill it to be able to |
128 |
+ switch back to it later. */ |
129 |
+ fcontext_t* ptr = static_cast<fcontext_t*>(res.data); |
130 |
+ *ptr = res.fctx; |
131 |
+ } |
132 |
+ if (ctx.exception) { |
133 |
+ std::rethrow_exception (ctx.exception); |
134 |
+ } |
135 |
+#endif |
136 |
} |
137 |
|
138 |
void |
139 |
@@ -146,7 +199,15 @@ pdns_makecontext |
140 |
args_t args; |
141 |
args.self = &ctx; |
142 |
args.work = &start; |
143 |
+ /* jumping to threadwrapper */ |
144 |
+#if BOOST_VERSION < 106100 |
145 |
jump_fcontext (reinterpret_cast<fcontext_t*>(&args.prev_ctx), |
146 |
static_cast<fcontext_t>(ctx.uc_mcontext), |
147 |
reinterpret_cast<intptr_t>(&args)); |
148 |
+#else |
149 |
+ transfer_t res = jump_fcontext (static_cast<fcontext_t>(ctx.uc_mcontext), |
150 |
+ &args); |
151 |
+ /* back from threadwrapper, updating the context */ |
152 |
+ ctx.uc_mcontext = res.fctx; |
153 |
+#endif |
154 |
} |