0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-16 08:58:20 +02:00

ircd::ios: Consolidate dispatch/post/defer interfaces; minor fixes.

This commit is contained in:
Jason Volk 2020-12-20 05:13:18 -08:00
parent 099c7754ff
commit 07ec766ff9
16 changed files with 224 additions and 280 deletions

View file

@ -158,8 +158,18 @@ try
if(!next_command()) if(!next_command())
break; break;
if(quit_when_done) if(unlikely(quit_when_done))
ircd::post{ircd::quit}; {
static ircd::ios::descriptor descriptor
{
"construct.console.quit"
};
ircd::dispatch
{
descriptor, ios::defer, ircd::quit
};
}
return; return;
} }

View file

@ -195,9 +195,14 @@ noexcept try
return; return;
}; };
ircd::post static ircd::ios::descriptor descriptor
{ {
ircd::quit "construct.smoketest"
};
ircd::dispatch
{
descriptor, ircd::ios::defer, ircd::quit
}; };
} }
}; };

View file

@ -111,7 +111,7 @@ construct::signals::set_handle()
{ {
static ircd::ios::descriptor desc static ircd::ios::descriptor desc
{ {
"construct::signals" "construct.signals"
}; };
auto handler auto handler

View file

@ -53,9 +53,9 @@ namespace ircd
inline void inline void
ircd::ctx::this_ctx::yield() ircd::ctx::this_ctx::yield()
{ {
ircd::post ios::dispatch
{ {
courtesy_yield_desc, ios::synchronous courtesy_yield_desc, ios::defer, ios::yield
}; };
} }

View file

@ -13,43 +13,26 @@
namespace ircd::ios namespace ircd::ios
{ {
IRCD_OVERLOAD(synchronous)
struct dispatch; struct dispatch;
struct defer;
struct post; IRCD_OVERLOAD(defer)
IRCD_OVERLOAD(yield)
} }
namespace ircd namespace ircd
{ {
using ios::dispatch; using ios::dispatch;
using ios::defer;
using ios::post;
} }
struct ircd::ios::dispatch struct ircd::ios::dispatch
{ {
dispatch(descriptor &, std::function<void ()>); dispatch(descriptor &, std::function<void ()>);
dispatch(descriptor &, synchronous_t, const std::function<void ()> &);
dispatch(descriptor &, synchronous_t);
dispatch(std::function<void ()>);
dispatch(synchronous_t, const std::function<void ()> &);
};
struct ircd::ios::defer dispatch(descriptor &, yield_t, const std::function<void ()> &);
{
defer(descriptor &, std::function<void ()>);
defer(descriptor &, synchronous_t, const std::function<void ()> &);
defer(descriptor &, synchronous_t);
defer(std::function<void ()>);
defer(synchronous_t, const std::function<void ()> &);
};
struct ircd::ios::post dispatch(descriptor &, defer_t, std::function<void ()>);
{
post(descriptor &, std::function<void ()>); dispatch(descriptor &, defer_t, yield_t, const std::function<void ()> &);
post(descriptor &, synchronous_t, const std::function<void ()> &);
post(descriptor &, synchronous_t); dispatch(descriptor &, defer_t, yield_t);
post(std::function<void ()>);
post(synchronous_t, const std::function<void ()> &);
}; };

View file

@ -49,8 +49,8 @@ namespace ircd::ios::profile
#include "descriptor.h" #include "descriptor.h"
#include "handler.h" #include "handler.h"
#include "asio.h" #include "asio.h"
#include "dispatch.h"
#include "empt.h" #include "empt.h"
#include "dispatch.h"
#include "epoll.h" #include "epoll.h"
inline const uint64_t & inline const uint64_t &

View file

@ -23,6 +23,7 @@ struct ircd::server::peer
struct err; struct err;
static constexpr const size_t &LINK_MAX{16}; static constexpr const size_t &LINK_MAX{16};
static ios::descriptor close_desc;
static conf::item<bool> enable_ipv6; static conf::item<bool> enable_ipv6;
static conf::item<size_t> link_min_default; static conf::item<size_t> link_min_default;
static conf::item<size_t> link_max_default; static conf::item<size_t> link_max_default;

View file

@ -530,6 +530,18 @@ noexcept
return ctx.note(); return ctx.note();
} }
namespace ircd::ctx
{
[[gnu::visibility("hidden")]]
extern ios::descriptor signal_desc;
}
decltype(ircd::ctx::signal_desc)
ircd::ctx::signal_desc
{
"ircd.ctx.signal"
};
/// Executes `func` sometime between executions of `ctx` with thread-safety /// Executes `func` sometime between executions of `ctx` with thread-safety
/// so `func` and `ctx` are never executed concurrently no matter how many /// so `func` and `ctx` are never executed concurrently no matter how many
/// threads the io_service has available to execute events on. /// threads the io_service has available to execute events on.
@ -537,7 +549,10 @@ void
ircd::ctx::signal(ctx &ctx, ircd::ctx::signal(ctx &ctx,
std::function<void ()> func) std::function<void ()> func)
{ {
ircd::dispatch(std::move(func)); ios::dispatch
{
signal_desc, ios::defer, std::move(func)
};
} }
/// Marks `ctx` for termination. Terminate is similar to interrupt() but the /// Marks `ctx` for termination. Terminate is similar to interrupt() but the
@ -721,7 +736,10 @@ noexcept
decltype(ircd::ctx::this_ctx::courtesy_yield_desc) decltype(ircd::ctx::this_ctx::courtesy_yield_desc)
ircd::ctx::this_ctx::courtesy_yield_desc ircd::ctx::this_ctx::courtesy_yield_desc
{ {
"ircd.ctx.courtesy_yield" "ircd.ctx.courtesy_yield",
nullptr,
nullptr,
true,
}; };
// set by the continuation object and the base frame. // set by the continuation object and the base frame.
@ -1241,11 +1259,17 @@ ircd::ctx::context::context(const string_view &name,
// parent is not itself a context as yielding is not possible anyway. // parent is not itself a context as yielding is not possible anyway.
assert(c->flags & POST || ircd::ctx::current); assert(c->flags & POST || ircd::ctx::current);
if(c->flags & POST) if(c->flags & POST)
ios::post(spawn_desc[0], std::move(spawn)); ios::dispatch
{
spawn_desc[0], ios::defer, std::move(spawn)
};
// (experimental) Branch to spawn via defer mechanism. // (experimental) Branch to spawn via defer mechanism.
else if(c->flags & DEFER) else if(c->flags & DEFER)
ios::defer(spawn_desc[1], ios::synchronous, std::move(spawn)); ios::dispatch
{
spawn_desc[1], ios::defer, ios::yield, std::move(spawn)
};
// Branch to spawn via dispatch mechanism. This context will yield while // Branch to spawn via dispatch mechanism. This context will yield while
// the spawning takes place on this stack. This is the closest to a direct // the spawning takes place on this stack. This is the closest to a direct
@ -1254,7 +1278,10 @@ ircd::ctx::context::context(const string_view &name,
// switch. Note: This is also the default method when no flags are given // switch. Note: This is also the default method when no flags are given
// and this parent is another context. // and this parent is another context.
else if(c->flags & DISPATCH || (true)) else if(c->flags & DISPATCH || (true))
ios::dispatch(spawn_desc[2], ios::synchronous, std::move(spawn)); ios::dispatch
{
spawn_desc[2], ios::yield, std::move(spawn)
};
} }
ircd::ctx::context::context(context &&other) ircd::ctx::context::context(context &&other)

View file

@ -982,9 +982,9 @@ ircd::fs::aio::system::submit(request &request)
std::bind(&system::chase, this) std::bind(&system::chase, this)
}; };
ircd::defer ios::dispatch
{ {
chase_descriptor, std::move(handler) chase_descriptor, ios::defer, std::move(handler)
}; };
} }

View file

@ -548,48 +548,54 @@ noexcept
// dispatch // dispatch
// //
namespace ircd::ios ircd::ios::dispatch::dispatch(descriptor &descriptor,
defer_t,
yield_t)
:dispatch
{
descriptor, defer, yield, []
{
}
}
{ {
extern descriptor dispatch_desc;
} }
decltype(ircd::ios::dispatch_desc) ircd::ios::dispatch::dispatch(descriptor &descriptor,
ircd::ios::dispatch_desc defer_t,
yield_t,
const std::function<void ()> &function)
{ {
"ircd.ios.dispatch" const ctx::uninterruptible::nothrow ui;
ctx::latch latch{1};
dispatch
{
descriptor, defer, [&function, &latch]
{
const unwind uw
{
[&latch]
{
latch.count_down();
}
}; };
function();
}
};
latch.wait();
}
[[gnu::hot]] [[gnu::hot]]
ircd::ios::dispatch::dispatch(std::function<void ()> function) ircd::ios::dispatch::dispatch(descriptor &descriptor,
:dispatch defer_t,
{ std::function<void ()> function)
dispatch_desc, std::move(function)
}
{
}
ircd::ios::dispatch::dispatch(synchronous_t,
const std::function<void ()> &function)
:dispatch
{
dispatch_desc, synchronous, std::move(function)
}
{ {
boost::asio::post(get(), handle(descriptor, std::move(function)));
} }
ircd::ios::dispatch::dispatch(descriptor &descriptor, ircd::ios::dispatch::dispatch(descriptor &descriptor,
synchronous_t) yield_t,
:dispatch
{
descriptor, synchronous, []
{
}
}
{
}
ircd::ios::dispatch::dispatch(descriptor &descriptor,
synchronous_t,
const std::function<void ()> &function) const std::function<void ()> &function)
{ {
assert(function); assert(function);
@ -635,145 +641,3 @@ ircd::ios::dispatch::dispatch(descriptor &descriptor,
assert(!ctx::current && handler::current == parent); assert(!ctx::current && handler::current == parent);
} }
//
// defer
//
namespace ircd::ios
{
extern descriptor defer_desc;
}
decltype(ircd::ios::defer_desc)
ircd::ios::defer_desc
{
"ircd.ios.defer",
};
[[gnu::hot]]
ircd::ios::defer::defer(std::function<void ()> function)
:defer
{
defer_desc, std::move(function)
}
{
}
ircd::ios::defer::defer(synchronous_t,
const std::function<void ()> &function)
:defer
{
defer_desc, synchronous, function
}
{
}
ircd::ios::defer::defer(descriptor &descriptor,
synchronous_t)
:defer
{
descriptor, synchronous, []
{
}
}
{
}
ircd::ios::defer::defer(descriptor &descriptor,
synchronous_t,
const std::function<void ()> &function)
{
const ctx::uninterruptible::nothrow ui;
ctx::latch latch(1);
defer(descriptor, [&function, &latch]
{
const unwind uw{[&latch]
{
latch.count_down();
}};
function();
});
latch.wait();
}
[[gnu::hot]]
ircd::ios::defer::defer(descriptor &descriptor,
std::function<void ()> function)
{
boost::asio::defer(get(), handle(descriptor, std::move(function)));
}
//
// post
//
namespace ircd::ios
{
extern descriptor post_desc;
}
decltype(ircd::ios::post_desc)
ircd::ios::post_desc
{
"ircd.ios.post"
};
[[gnu::hot]]
ircd::ios::post::post(std::function<void ()> function)
:post
{
post_desc, std::move(function)
}
{
}
ircd::ios::post::post(synchronous_t,
const std::function<void ()> &function)
:post
{
post_desc, synchronous, function
}
{
}
ircd::ios::post::post(descriptor &descriptor,
synchronous_t)
:post
{
descriptor, synchronous, []
{
}
}
{
}
ircd::ios::post::post(descriptor &descriptor,
synchronous_t,
const std::function<void ()> &function)
{
const ctx::uninterruptible::nothrow ui;
ctx::latch latch(1);
post(descriptor, [&function, &latch]
{
const unwind uw{[&latch]
{
latch.count_down();
}};
function();
});
latch.wait();
}
[[gnu::hot]]
ircd::ios::post::post(descriptor &descriptor,
std::function<void ()> function)
{
boost::asio::post(get(), handle(descriptor, std::move(function)));
}

View file

@ -458,7 +458,7 @@ ircd::log::vlog_threadsafe(const log &log,
// The pointer to the logger is copied to the main thread. // The pointer to the logger is copied to the main thread.
auto *const logp{&log}; auto *const logp{&log};
ircd::post(descriptor, [lev, str(std::move(str)), logp] ircd::dispatch{descriptor, ios::defer, [lev, str(std::move(str)), logp]
{ {
// If that named logger was destroyed while this closure was // If that named logger was destroyed while this closure was
// travelling to the main thread then we just discard this message. // travelling to the main thread then we just discard this message.
@ -469,7 +469,7 @@ ircd::log::vlog_threadsafe(const log &log,
{ {
return copy(out, string_view{str}); return copy(out, string_view{str});
}); });
}); }};
} }
ircd::log::vlog::vlog(const log &log, ircd::log::vlog::vlog(const log &log,

View file

@ -1543,10 +1543,10 @@ try
static const ilist<mutable_buffer> bufs{buf}; static const ilist<mutable_buffer> bufs{buf};
if(SSL_peek(ssl.native_handle(), buf, sizeof(buf)) > 0) if(SSL_peek(ssl.native_handle(), buf, sizeof(buf)) > 0)
{ {
ircd::post(desc_wait[1], [handle(std::move(handle))] ircd::dispatch{desc_wait[1], ios::defer, [handle(std::move(handle))]
{ {
handle(error_code{}); handle(error_code{});
}); }};
return; return;
} }

View file

@ -696,6 +696,16 @@ decltype(ircd::server::peers)
ircd::server::peers ircd::server::peers
{}; {};
//
// server::peer
//
decltype(ircd::server::peer::close_desc)
ircd::server::peer::close_desc
{
"ircd.server.peer.close"
};
decltype(ircd::server::peer::enable_ipv6) decltype(ircd::server::peer::enable_ipv6)
ircd::server::peer::enable_ipv6 ircd::server::peer::enable_ipv6
{ {
@ -1244,10 +1254,13 @@ noexcept try
if(err_has()) if(err_has())
{ {
// The peer can't be closed quite yet b/c the tag hasn't finished. // The peer can't be closed quite yet b/c the tag hasn't finished.
defer{[this] ircd::dispatch
{
close_desc, ios::defer, [this]
{ {
close(); close();
}}; }
};
return; return;
} }

View file

@ -445,9 +445,14 @@ ircd::util::a2u(const mutable_buffer &out,
ircd::util::unwind_defer::~unwind_defer() ircd::util::unwind_defer::~unwind_defer()
noexcept noexcept
{ {
ircd::defer static ios::descriptor descriptor
{ {
std::move(func) "ircd.unwind"
};
ircd::dispatch
{
descriptor, ios::defer, std::move(func)
}; };
} }

View file

@ -1814,12 +1814,30 @@ console_cmd__ios__history(opt &out, const string_view &line)
bool bool
console_cmd__ios__depth(opt &out, const string_view &line) console_cmd__ios__depth(opt &out, const string_view &line)
{ {
static ios::descriptor dispatch_desc
{
"ircd.console.depth.dispatch",
};
static ios::descriptor post_desc
{
"ircd.console.depth.post",
};
static ios::descriptor defer_desc
{
"ircd.console.latency.defer",
nullptr,
nullptr,
true,
};
uint64_t returned, executed, started; uint64_t returned, executed, started;
// ios::dispatch // ios::dispatch
{ {
started = ios::epoch(); started = ios::epoch();
ios::dispatch(ios::synchronous, [&executed] ios::dispatch(dispatch_desc, ios::yield, [&executed]
{ {
executed = ios::epoch(); executed = ios::epoch();
}); });
@ -1833,27 +1851,10 @@ console_cmd__ios__depth(opt &out, const string_view &line)
<< "disp rtt: " << (returned - started) << std::endl << "disp rtt: " << (returned - started) << std::endl
<< std::endl; << std::endl;
// ios::defer
{
started = ios::epoch();
ios::defer(ios::synchronous, [&executed]
{
executed = ios::epoch();
});
returned = ios::epoch();
}
out
<< "defer send: " << (executed - started) << std::endl
<< "defer recv: " << (returned - executed) << std::endl
<< "defer rtt: " << (returned - started) << std::endl
<< std::endl;
// ios::post // ios::post
{ {
started = ios::epoch(); started = ios::epoch();
ios::post(ios::synchronous, [&executed] ios::dispatch(post_desc, ios::defer, ios::yield, [&executed]
{ {
executed = ios::epoch(); executed = ios::epoch();
}); });
@ -1867,6 +1868,23 @@ console_cmd__ios__depth(opt &out, const string_view &line)
<< "post rtt: " << (returned - started) << std::endl << "post rtt: " << (returned - started) << std::endl
<< std::endl; << std::endl;
// ios::defer
{
started = ios::epoch();
ios::dispatch(defer_desc, ios::defer, ios::yield, [&executed]
{
executed = ios::epoch();
});
returned = ios::epoch();
}
out
<< "defer send: " << (executed - started) << std::endl
<< "defer recv: " << (returned - executed) << std::endl
<< "defer rtt: " << (returned - started) << std::endl
<< std::endl;
return true; return true;
} }
@ -1874,7 +1892,25 @@ console_cmd__ios__depth(opt &out, const string_view &line)
bool bool
console_cmd__ios__latency(opt &out, const string_view &line) console_cmd__ios__latency(opt &out, const string_view &line)
{ {
volatile long long returned, executed, started; static ios::descriptor dispatch_desc
{
"ircd.console.latency.dispatch"
};
static ios::descriptor post_desc
{
"ircd.console.latency.post"
};
static ios::descriptor defer_desc
{
"ircd.console.latency.defer",
nullptr,
nullptr,
true,
};
long long returned, executed, started;
// control // control
{ {
@ -1910,7 +1946,7 @@ console_cmd__ios__latency(opt &out, const string_view &line)
started = prof::cycles(); started = prof::cycles();
asm volatile ("lfence"); asm volatile ("lfence");
ios::dispatch(ios::synchronous, [&executed] ios::dispatch(dispatch_desc, ios::yield, [&executed]
{ {
__sync_synchronize(); __sync_synchronize();
asm volatile ("lfence"); asm volatile ("lfence");
@ -1930,36 +1966,6 @@ console_cmd__ios__latency(opt &out, const string_view &line)
<< "disp rtt: " << (returned - started) << std::endl << "disp rtt: " << (returned - started) << std::endl
<< std::endl; << std::endl;
//
// ios::defer
//
{
__sync_synchronize();
asm volatile ("lfence");
started = prof::cycles();
asm volatile ("lfence");
ios::defer(ios::synchronous, [&executed]
{
__sync_synchronize();
asm volatile ("lfence");
executed = prof::cycles();
asm volatile ("lfence");
});
__sync_synchronize();
asm volatile ("lfence");
returned = prof::cycles();
asm volatile ("lfence");
}
out
<< "defer send: " << (executed - started) << std::endl
<< "defer recv: " << (returned - executed) << std::endl
<< "defer rtt: " << (returned - started) << std::endl
<< std::endl;
// //
// ios::post // ios::post
// //
@ -1970,7 +1976,7 @@ console_cmd__ios__latency(opt &out, const string_view &line)
started = prof::cycles(); started = prof::cycles();
asm volatile ("lfence"); asm volatile ("lfence");
ios::post(ios::synchronous, [&executed] ios::dispatch(post_desc, ios::defer, ios::yield, [&executed]
{ {
__sync_synchronize(); __sync_synchronize();
asm volatile ("lfence"); asm volatile ("lfence");
@ -1990,6 +1996,36 @@ console_cmd__ios__latency(opt &out, const string_view &line)
<< "post rtt: " << (returned - started) << std::endl << "post rtt: " << (returned - started) << std::endl
<< std::endl; << std::endl;
//
// ios::defer
//
{
__sync_synchronize();
asm volatile ("lfence");
started = prof::cycles();
asm volatile ("lfence");
ios::dispatch(defer_desc, ios::defer, ios::yield, [&executed]
{
__sync_synchronize();
asm volatile ("lfence");
executed = prof::cycles();
asm volatile ("lfence");
});
__sync_synchronize();
asm volatile ("lfence");
returned = prof::cycles();
asm volatile ("lfence");
}
out
<< "defer send: " << (executed - started) << std::endl
<< "defer recv: " << (returned - executed) << std::endl
<< "defer rtt: " << (returned - started) << std::endl
<< std::endl;
return true; return true;
} }
#endif #endif

View file

@ -34,13 +34,13 @@ _cmd__die(const m::event &event,
{ {
static ios::descriptor descriptor static ios::descriptor descriptor
{ {
"s_control die" "ircd.m.control.die"
}; };
ircd::post(descriptor, [] ircd::dispatch
{ {
ircd::quit(); descriptor, ios::defer, ircd::quit
}); };
ctx::yield(); ctx::yield();
} }