Skip to content

Commit

Permalink
Merge pull request #3479 from nlyan/mtdocs
Browse files Browse the repository at this point in the history
Add some comments to our use of Boost context
  • Loading branch information
ahupowerdns committed Feb 28, 2016
2 parents c199c34 + 440284e commit 8fc7a49
Showing 1 changed file with 28 additions and 0 deletions.
28 changes: 28 additions & 0 deletions pdns/mtasker_fcontext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,23 @@
using boost::context::make_fcontext;

#if BOOST_VERSION < 105600
/* Note: This typedef means functions taking fcontext_t*, like jump_fcontext(),
* now require a reinterpret_cast rather than a static_cast, since we're
* casting from pdns_context_t->uc_mcontext, which is void**, to
* some_opaque_struct**. In later versions fcontext_t is already void*. So if
* you remove this, then fix the ugly.
*/
using fcontext_t = boost::context::fcontext_t*;

/* Emulate the >= 1.56 API for Boost 1.52 through 1.55 */
static inline intptr_t
jump_fcontext (fcontext_t* const ofc, fcontext_t const nfc,
intptr_t const arg) {
/* If the fcontext_t is preallocated then use it, otherwise allocate one
* on the stack ('self') and stash a pointer away in *ofc so the returning
* MThread can access it. This is safe because we're suspended, so the
* context object always outlives the jump.
*/
if (*ofc) {
return boost::context::jump_fcontext (*ofc, nfc, arg);
} else {
Expand All @@ -31,6 +43,9 @@ static_assert (std::is_pointer<fcontext_t>::value,
"Boost Context has changed the fcontext_t type again :-(");
#endif

/* Boost context only provides a means of passing a single argument across a
* jump. args_t simply provides a way to pass more by reference.
*/
struct args_t {
fcontext_t prev_ctx = nullptr;
pdns_ucontext_t* self = nullptr;
Expand All @@ -41,6 +56,15 @@ extern "C" {
static
void
threadWrapper (intptr_t const xargs) {
/* Access the args passed from pdns_makecontext, and copy them directly from
* the calling stack on to ours (we're now using the MThreads stack).
* This saves heap allocating an args object, at the cost of an extra
* context switch to fashion this constructor-like init phase. The work
* function object is still only moved after we're (re)started, so may
* still be set or changed after a call to pdns_makecontext. This matches
* the behaviour of the System V implementation, which can inherently only
* be passed ints and pointers.
*/
auto args = reinterpret_cast<args_t*>(xargs);
auto ctx = args->self;
auto work = args->work;
Expand All @@ -55,6 +79,7 @@ threadWrapper (intptr_t const xargs) {
ctx->exception = std::current_exception();
}

/* Emulate the System V uc_link feature. */
auto const next_ctx = ctx->uc_link->uc_mcontext;
jump_fcontext (reinterpret_cast<fcontext_t*>(&ctx->uc_mcontext),
static_cast<fcontext_t>(next_ctx),
Expand All @@ -71,6 +96,9 @@ pdns_ucontext_t::pdns_ucontext_t

pdns_ucontext_t::~pdns_ucontext_t
() {
/* There's nothing to delete here since fcontext doesn't require anything
* to be heap allocated.
*/
}

void
Expand Down

0 comments on commit 8fc7a49

Please sign in to comment.