0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-25 16:22:35 +01:00

ircd::ctx: Add critical_assertion debugging tool.

This commit is contained in:
Jason Volk 2017-09-27 18:29:29 -07:00
parent bc9b0e990c
commit c4a6addd5a
2 changed files with 55 additions and 7 deletions

View file

@ -75,12 +75,16 @@ namespace ircd::ctx
/// Interface to the currently running context
namespace ircd::ctx { inline namespace this_ctx
{
struct critical_assertion; // Assert no yielding for a section
// Always set to the currently running context or null for main stack
extern __thread struct ctx *current;
ctx &cur(); // Assumptional reference to *current
void wait(); // Returns when context is woken up.
void yield(); // Allow other contexts to run before returning.
void interruption_point(); // throws interrupted if interruption_requested()
bool interruption_requested(); // interruption(cur())
@ -122,6 +126,23 @@ namespace ircd
using ctx::sleep;
}
/// An instance of critical_assertion detects an attempt to context switch
/// when the developer specifically does not want any yielding in that section
/// or anywhere up the stack from it. This device does not prevent a switch
/// and may carry no meaning outside of debug-mode compilation. It is good
/// practice to use this device even when it appears obvious the section's
/// callgraph has no chance of yielding; code changes, and everything up
/// up the graph can change without taking notice of your section.
///
class ircd::ctx::this_ctx::critical_assertion
{
bool theirs;
public:
critical_assertion();
~critical_assertion() noexcept;
};
/// This overload matches ::sleep() and acts as a drop-in for ircd contexts.
/// interruption point.
inline void

View file

@ -376,21 +376,48 @@ ircd::ctx::id(const ctx &ctx)
// ctx/continuation.h
//
//
// Support for critical_assertion (ctx.h)
//
namespace ircd::ctx
{
bool critical_asserted;
}
ircd::ctx::this_ctx::critical_assertion::critical_assertion()
:theirs{critical_asserted}
{
critical_asserted = true;
}
ircd::ctx::this_ctx::critical_assertion::~critical_assertion()
noexcept
{
assert(critical_asserted);
critical_asserted = theirs;
}
//
// continuation
//
ircd::ctx::continuation::continuation(ctx *const &self)
:self{self}
{
mark(prof::event::CUR_YIELD);
assert(self != nullptr);
assert(self->notes <= 1);
ircd::ctx::current = nullptr;
mark(prof::event::CUR_YIELD);
assert(!critical_asserted);
assert(self != nullptr);
assert(self->notes <= 1);
ircd::ctx::current = nullptr;
}
ircd::ctx::continuation::~continuation()
noexcept
{
ircd::ctx::current = self;
self->notes = 1;
mark(prof::event::CUR_CONTINUE);
ircd::ctx::current = self;
self->notes = 1;
mark(prof::event::CUR_CONTINUE);
}
ircd::ctx::continuation::operator boost::asio::yield_context &()