From 505fe310a8bf44b45e37c216d69b2d0bd05b147b Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Thu, 18 Jun 2020 03:20:14 -0700 Subject: [PATCH] ircd::ctx: Inline various codepaths leading to flags(ctx). ircd::ctx: Inline cheap prof::get() wrappings. --- include/ircd/ctx/ctx.h | 53 +++++++++++++++++++++++ include/ircd/ctx/this_ctx.h | 49 +++++++++++++++++++++ include/ircd/ctx/uninterruptible.h | 50 ---------------------- ircd/ctx.cc | 69 ------------------------------ 4 files changed, 102 insertions(+), 119 deletions(-) diff --git a/include/ircd/ctx/ctx.h b/include/ircd/ctx/ctx.h index 0e1c6d456..d5e8bffb2 100644 --- a/include/ircd/ctx/ctx.h +++ b/include/ircd/ctx/ctx.h @@ -137,6 +137,59 @@ namespace ircd using ctx::assert_main_thread; } +/// Marks `ctx` for whether to allow or suppress interruption. Suppression +/// does not ignore an interrupt itself, it only ignores the interruption +/// points. Thus when a suppression ends if the interrupt flag was ever set +/// the next interruption point will throw as expected. +inline void +ircd::ctx::interruptible(ctx &ctx, + const bool &b) +noexcept +{ + flags(ctx) ^= (flags(ctx) ^ (ulong(b) - 1)) & context::NOINTERRUPT; + assert(bool(flags(ctx) & context::NOINTERRUPT) == !b); + assert(interruptible(ctx) == b); +} + +/// Indicates if `ctx` was terminated; does not clear the flag +inline bool +ircd::ctx::termination(const ctx &c) +noexcept +{ + return flags(c) & context::TERMINATED; +} + +/// Indicates if `ctx` was interrupted; does not clear the flag +inline bool +ircd::ctx::interruption(const ctx &c) +noexcept +{ + return flags(c) & context::INTERRUPTED; +} + +inline bool +ircd::ctx::interruptible(const ctx &ctx) +noexcept +{ + return ~flags(ctx) & context::NOINTERRUPT; +} + +/// Returns the cycle count for `ctx` +inline const ulong & +ircd::ctx::cycles(const ctx &ctx) +noexcept +{ + return prof::get(ctx, prof::event::CYCLES); +} + +/// Returns the yield count for `ctx` +inline const uint64_t & +ircd::ctx::epoch(const ctx &ctx) +noexcept +{ + return prof::get(ctx, prof::event::YIELD); +} + inline void __attribute__((always_inline)) ircd::ctx::assert_main_thread() diff --git a/include/ircd/ctx/this_ctx.h b/include/ircd/ctx/this_ctx.h index c9cc01db5..b4f4cbca7 100644 --- a/include/ircd/ctx/this_ctx.h +++ b/include/ircd/ctx/this_ctx.h @@ -18,8 +18,14 @@ namespace ircd::ctx { inline namespace this_ctx const uint64_t &id() noexcept; // Unique ID for cur ctx string_view name() noexcept; // Optional label for cur ctx ulong cycles() noexcept; // misc profiling related + bool interruption_requested() noexcept; // interruption(cur()) void interruption_point(); // throws if interruption_requested() + bool interruptible() noexcept; + + void interruptible(const bool &, std::nothrow_t) noexcept; + void interruptible(const bool &); + void yield(); // Allow other contexts to run before returning. }} @@ -43,6 +49,49 @@ noexcept return current? name(cur()) : "*"_sv; } +inline void +ircd::ctx::this_ctx::interruptible(const bool &b, + std::nothrow_t) +noexcept +{ + interruptible(cur(), b); +} + +inline bool +ircd::ctx::this_ctx::interruptible() +noexcept +{ + return interruptible(cur()); +} + +/// Throws interrupted if the currently running context was interrupted +/// and clears the interrupt flag. +inline void +ircd::ctx::this_ctx::interruptible(const bool &b) +{ + const bool theirs + { + interruptible(cur()) + }; + + if(unlikely(theirs && !b && interruption_requested())) + interruption_point(); + + interruptible(cur(), b); + + if(unlikely(!theirs && b && interruption_requested())) + interruption_point(); +} + +/// Returns true if the currently running context was interrupted and clears +/// the interrupt flag. +inline bool +ircd::ctx::this_ctx::interruption_requested() +noexcept +{ + return interruption(cur()) || termination(cur()); +} + /// Calculate the current TSC (reference cycle count) accumulated for this /// context only. This is done by first calculating a cycle count for the /// current slice/epoch (see: ctx/prof.h) which is where the RDTSC sample diff --git a/include/ircd/ctx/uninterruptible.h b/include/ircd/ctx/uninterruptible.h index f2e9f5d3c..b611857d0 100644 --- a/include/ircd/ctx/uninterruptible.h +++ b/include/ircd/ctx/uninterruptible.h @@ -11,20 +11,10 @@ #pragma once #define HAVE_IRCD_CTX_UNINTERRUPTIBLE_H -namespace ircd::ctx -{ - bool interruptible(const ctx &) noexcept; - void interruptible(ctx &, const bool &) noexcept; -} - namespace ircd::ctx { inline namespace this_ctx { struct uninterruptible; - - bool interruptible() noexcept; - void interruptible(const bool &); - void interruptible(const bool &, std::nothrow_t) noexcept; }} /// An instance of uninterruptible will suppress interrupts sent to the @@ -101,43 +91,3 @@ noexcept { interruptible(theirs, std::nothrow); } - -// -// interruptible -// - -inline void -ircd::ctx::this_ctx::interruptible(const bool &b, - std::nothrow_t) -noexcept -{ - interruptible(cur(), b); -} - -inline bool -ircd::ctx::this_ctx::interruptible() -noexcept -{ - return interruptible(cur()); -} - -/// Marks `ctx` for whether to allow or suppress interruption. Suppression -/// does not ignore an interrupt itself, it only ignores the interruption -/// points. Thus when a suppression ends if the interrupt flag was ever set -/// the next interruption point will throw as expected. -inline void -ircd::ctx::interruptible(ctx &ctx, - const bool &b) -noexcept -{ - flags(ctx) ^= (flags(ctx) ^ (ulong(b) - 1)) & context::NOINTERRUPT; - assert(bool(flags(ctx) & context::NOINTERRUPT) == !b); - assert(interruptible(ctx) == b); -} - -inline bool -ircd::ctx::interruptible(const ctx &ctx) -noexcept -{ - return ~flags(ctx) & context::NOINTERRUPT; -} diff --git a/ircd/ctx.cc b/ircd/ctx.cc index 63aa26c68..ed0e1c092 100644 --- a/ircd/ctx.cc +++ b/ircd/ctx.cc @@ -572,33 +572,6 @@ noexcept return ctx.finished(); } -/// Indicates if `ctx` was terminated; does not clear the flag -[[gnu::hot]] -bool -ircd::ctx::termination(const ctx &c) -noexcept -{ - return c.flags & context::TERMINATED; -} - -/// Indicates if `ctx` was interrupted; does not clear the flag -[[gnu::hot]] -bool -ircd::ctx::interruption(const ctx &c) -noexcept -{ - return c.flags & context::INTERRUPTED; -} - -/// Returns the cycle count for `ctx` -[[gnu::hot]] -const ulong & -ircd::ctx::cycles(const ctx &ctx) -noexcept -{ - return prof::get(ctx, prof::event::CYCLES); -} - /// Returns the IO priority nice-value [[gnu::hot]] const int8_t & @@ -617,15 +590,6 @@ noexcept return ctx.nice; } -/// Returns the yield count for `ctx` -[[gnu::hot]] -const uint64_t & -ircd::ctx::epoch(const ctx &ctx) -noexcept -{ - return prof::get(ctx, prof::event::YIELD); -} - /// Returns the notification count for `ctx` [[gnu::hot]] const int32_t & @@ -789,15 +753,6 @@ ircd::ctx::this_ctx::interruption_point() return cur().interruption_point(); } -/// Returns true if the currently running context was interrupted and clears -/// the interrupt flag. -bool -ircd::ctx::this_ctx::interruption_requested() -noexcept -{ - return interruption(cur()) || termination(cur()); -} - /// Returns unique ID of currently running context [[gnu::hot]] const uint64_t & @@ -808,30 +763,6 @@ noexcept return current? id(cur()) : zero; } -// -// interruptible -// - -/// Throws interrupted if the currently running context was interrupted -/// and clears the interrupt flag. -[[gnu::hot]] -void -ircd::ctx::this_ctx::interruptible(const bool &b) -{ - const bool theirs - { - interruptible(cur()) - }; - - if(theirs && !b) - interruption_point(); - - interruptible(cur(), b); - - if(!theirs && b) - interruption_point(); -} - // // critical_assertion //