From 09c282fd8e9d93a52313ff7c76439e4fcb4e4586 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Fri, 27 Apr 2018 19:04:31 -0700 Subject: [PATCH] ircd::ctx: Add stack_usage_assertion; move stack_usage_here() into this_ctx::. --- include/ircd/ctx/prof.h | 1 - include/ircd/ctx/this_ctx.h | 17 +++++++++++++++++ ircd/ctx.cc | 35 ++++++++++++++++++++++++++++------- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/include/ircd/ctx/prof.h b/include/ircd/ctx/prof.h index 1beb9c9e6..2686c3a95 100644 --- a/include/ircd/ctx/prof.h +++ b/include/ircd/ctx/prof.h @@ -14,7 +14,6 @@ namespace ircd::ctx { size_t stack_usage_here(const ctx &) __attribute__((noinline)); - size_t stack_usage_here(); } /// Profiling for the context system. diff --git a/include/ircd/ctx/this_ctx.h b/include/ircd/ctx/this_ctx.h index e00d64566..c49ba0ebd 100644 --- a/include/ircd/ctx/this_ctx.h +++ b/include/ircd/ctx/this_ctx.h @@ -29,6 +29,9 @@ inline namespace this_ctx void interruption_point(); // throws interrupted if interruption_requested() bool interruption_requested(); // interruption(cur()) + struct stack_usage_assertion; // Assert safety factor (see ctx/prof.h) + size_t stack_usage_here(); // calculates stack usage at call. + // Return remaining time if notified; or <= 0 if not, and timeout thrown on throw overloads microseconds wait(const microseconds &, const std::nothrow_t &); template nothrow_overload wait(const duration &); @@ -51,6 +54,20 @@ namespace ircd::ctx extern __thread ctx *current; } +/// An instance of stack_usage_assertion is placed on a ctx stack where one +/// wants to test the stack usage at both construction and destruction points +/// to ensure it is less than the value set in ctx::prof::settings which is +/// generally some engineering safety factor of 2-3 etc. This should not be +/// entirely relied upon except during debug builds, however we may try to +/// provide an optimized build mode enabling these to account for any possible +/// differences in the stack between the environments. +/// +struct ircd::ctx::this_ctx::stack_usage_assertion +{ + stack_usage_assertion(); + ~stack_usage_assertion() noexcept; +}; + /// An instance of critical_assertion detects an attempt to context switch. /// /// For when the developer specifically does not want any yielding in a diff --git a/ircd/ctx.cc b/ircd/ctx.cc index 7c23cc399..b962b5243 100644 --- a/ircd/ctx.cc +++ b/ircd/ctx.cc @@ -490,6 +490,13 @@ ircd::ctx::this_ctx::yield() while(!done); } +size_t +ircd::ctx::this_ctx::stack_usage_here() +{ + assert(current); + return stack_usage_here(cur()); +} + /// Throws interrupted if the currently running context was interrupted /// and clears the interrupt flag. void @@ -562,6 +569,27 @@ noexcept critical_asserted = theirs; } +// +// stack_usage_assertion +// + +ircd::ctx::this_ctx::stack_usage_assertion::stack_usage_assertion() +{ + #ifndef NDEBUG + const auto stack_usage(stack_usage_here()); + assert(stack_usage < cur().stack_max * prof::settings.stack_usage_assertion); + #endif +} + +ircd::ctx::this_ctx::stack_usage_assertion::~stack_usage_assertion() +noexcept +{ + #ifdef RB_DEBUG + const auto stack_usage(stack_usage_here()); + assert(stack_usage < cur().stack_max * prof::settings.stack_usage_assertion); + #endif +} + /////////////////////////////////////////////////////////////////////////////// // // ctx/continuation.h @@ -1070,13 +1098,6 @@ ircd::ctx::prof::check_stack() } } -size_t -ircd::ctx::stack_usage_here() -{ - assert(current); - return stack_usage_here(*current); -} - size_t ircd::ctx::stack_usage_here(const ctx &ctx) {