|
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 |
} |