From 249ba02faa556fb5f2eef51f6d097fadfea18479 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Mon, 5 Sep 2016 08:53:36 -0700 Subject: [PATCH] Introduce userspace contexts. --- configure.ac | 12 ++--- include/ircd/ctx.h | 74 ++++++++++++++++++++++++++ include/ircd/ctx_ctx.h | 55 ++++++++++++++++++++ include/ircd/stdinc.h | 2 + ircd/Makefile.am | 3 +- ircd/ctx.cc | 115 +++++++++++++++++++++++++++++++++++++++++ tools/boostrap.sh | 20 +++++-- 7 files changed, 271 insertions(+), 10 deletions(-) create mode 100644 include/ircd/ctx.h create mode 100644 include/ircd/ctx_ctx.h create mode 100644 ircd/ctx.cc diff --git a/configure.ac b/configure.ac index 999c69248..a5b89acf1 100644 --- a/configure.ac +++ b/configure.ac @@ -774,7 +774,7 @@ dnl boost support dnl BOOST_VERSION_MIN="1.56" -BOOST_BUILT_LIBS="system,filesystem" +BOOST_BUILT_LIBS="system,filesystem,context,coroutine" AC_MSG_CHECKING([whether you asked to use boost sources included here]) AC_ARG_WITH(included-boost, @@ -801,7 +801,7 @@ AC_HELP_STRING([--with-included-boost[[[=shared]]]], [Use the boost sources from fi boost_linkage="$withval" - bash tools/boostrap.sh $BTOOLSET $BOOST_BUILT_LIBS release shared single + bash tools/boostrap.sh $BTOOLSET $BOOST_BUILT_LIBS release shared multi if [[ $? != 0 ]]; then AC_MSG_ERROR([Failed to build included boost.]) fi @@ -837,16 +837,16 @@ AC_HELP_STRING([--with-included-boost[[[=shared]]]], [Use the boost sources from if [[ "$boost_linkage" = "shared" ]]; then AM_COND_IF([MINGW], [ - AC_SUBST(BOOST_LIBS, ["-lboost_filesystem-mgw53-1_61.dll -lboost_system-mgw53-1_61.dll"]) + AC_SUBST(BOOST_LIBS, ["-lboost_coroutine-mgw53-1_61.dll -lboost_context-mgw53-1_61.dll -lboost_thread-mgw53-1_61.dll -lboost_filesystem-mgw53-1_61.dll -lboost_system-mgw53-1_61.dll"]) ], [ - AC_SUBST(BOOST_LIBS, ["-lboost_filesystem -lboost_system -lpthread"]) + AC_SUBST(BOOST_LIBS, ["-lboost_coroutine -lboost_context -lboost_thread -lboost_filesystem -lboost_system -lpthread"]) ]) else AM_COND_IF([MINGW], [ - AC_SUBST(BOOST_LIBS, ["$boost_libdir/libboost_filesystem-mgw53-1_61.dll.a $boost_libdir/libboost_system-mgw53-1_61.dll.a"]) + AC_SUBST(BOOST_LIBS, ["$boost_libdir/libboost_coroutine-mgw53-1_61.dll.a $boost_libdir/libboost_context-mgw53-1_61.dll.a $boost_libdir/libboost_thread-mgw53-1_61.dll.a $boost_libdir/libboost_filesystem-mgw53-1_61.dll.a $boost_libdir/libboost_system-mgw53-1_61.dll.a"]) ], [ - AC_SUBST(BOOST_LIBS, ["-lboost_filesystem -lboost_system -lpthread"]) + AC_SUBST(BOOST_LIBS, ["-lboost_coroutine -lboost_context -lboost_thread -lboost_filesystem -lboost_system -lpthread"]) dnl AC_SUBST(BOOST_LIBS, ["$boost_libdir/libboost_filesystem.a"]) dnl AC_SUBST(BOOST_LIBS, ["$boost_libdir/libboost_system.a"]) ]) diff --git a/include/ircd/ctx.h b/include/ircd/ctx.h new file mode 100644 index 000000000..97f8321d4 --- /dev/null +++ b/include/ircd/ctx.h @@ -0,0 +1,74 @@ +/* + * charybdis: oh just a little chat server + * ctx.h: userland context switching (stackful coroutines) + * + * Copyright (C) 2016 Charybdis Development Team + * Copyright (C) 2016 Jason Volk + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#define HAVE_IRCD_CTX_H + +#ifdef __cplusplus +namespace ircd { +namespace ctx { + +IRCD_EXCEPTION(ircd::error, error) +IRCD_EXCEPTION(error, interrupted) + +const auto DEFAULT_STACK_SIZE = 64_KiB; + +struct ctx; +class context +{ + using ptr = std::unique_ptr; + using function = std::function; + + ptr c; + + public: + void join(); + ctx *detach(); + context &swap(context &) noexcept; + + context(const size_t &stack_size, const function &); + context(const function &); + context(context &&) noexcept = default; + context(const context &) = delete; + ~context() noexcept; +}; + +extern __thread struct ctx *current; + +void swap(context &a, context &b) noexcept; + +inline +ctx &cur() +{ + assert(current); + return *current; +} + +} // namespace ctx + +using ctx::cur; +using ctx::context; + +} // namespace ircd +#endif // __cplusplus diff --git a/include/ircd/ctx_ctx.h b/include/ircd/ctx_ctx.h new file mode 100644 index 000000000..d24ca0da6 --- /dev/null +++ b/include/ircd/ctx_ctx.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 Charybdis Development Team + * Copyright (C) 2016 Jason Volk + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +namespace ircd { +namespace ctx { + +struct ctx +{ + boost::asio::io_service::strand strand; + boost::asio::steady_timer alarm; + size_t stack_size; + const uint8_t *stack_base; + boost::asio::yield_context *yc; + + operator boost::asio::yield_context(); + + void operator()(boost::asio::yield_context, const std::function); + + ctx(const size_t &stack_size = DEFAULT_STACK_SIZE, + boost::asio::io_service *const &ios = ircd::ios); + + ctx(const ctx &) = delete; + ~ctx() noexcept; +}; + +inline +ctx::operator boost::asio::yield_context() +{ + return *yc; +} + +} // namespace ctx +} // namespace ircd diff --git a/include/ircd/stdinc.h b/include/ircd/stdinc.h index 98bc9b8a7..728437124 100644 --- a/include/ircd/stdinc.h +++ b/include/ircd/stdinc.h @@ -33,6 +33,7 @@ namespace ircd using std::end; using std::get; using ostream = std::ostream; + namespace ph = std::placeholders; using namespace std::string_literals; } @@ -77,6 +78,7 @@ namespace ircd #include "mode_table.h" #include "mode_lease.h" #include "snomask.h" +#include "ctx.h" #include "cache.h" #include "whowas.h" diff --git a/ircd/Makefile.am b/ircd/Makefile.am index 89e7912f0..58e64b566 100644 --- a/ircd/Makefile.am +++ b/ircd/Makefile.am @@ -41,7 +41,8 @@ libircd_la_SOURCES = \ modules.cc \ snomask.cc \ info.cc \ - cmd.cc + cmd.cc \ + ctx.cc #authproc.cc \ #bandbi.cc \ diff --git a/ircd/ctx.cc b/ircd/ctx.cc new file mode 100644 index 000000000..3942b2775 --- /dev/null +++ b/ircd/ctx.cc @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2016 Charybdis Development Team + * Copyright (C) 2016 Jason Volk + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +using namespace ircd; + +/****************************************************************************** + * ctx.h + */ +__thread ctx::ctx *ctx::current; + +ircd::ctx::context::context(const size_t &stack_size, + const function &func) +:c{std::make_unique(stack_size)} +{ + static const boost::coroutines::attributes attrs + { + stack_size, + boost::coroutines::stack_unwind + }; + + const auto bound(std::bind(&ctx::operator(), c.get(), ph::_1, func)); + boost::asio::spawn(c->strand, bound, attrs); +} + +ircd::ctx::context::context(const function &func) +:context +{ + DEFAULT_STACK_SIZE, + func +} +{ +} + +ircd::ctx::context::~context() +noexcept +{ + join(); +} + +void +ircd::ctx::context::join() +{ + +} + +ircd::ctx::context & +ircd::ctx::context::swap(context &other) +noexcept +{ + std::swap(c, other.c); + return *this; +} + +ircd::ctx::ctx * +ircd::ctx::context::detach() +{ + return c.release(); +} + +void +ircd::ctx::swap(context &a, context &b) +noexcept +{ + a.swap(b); +} + +/****************************************************************************** + * ctx_ctx.h + */ +ctx::ctx::ctx(const size_t &stack_size, + boost::asio::io_service *const &ios) +:strand{*ios} +,alarm{*ios} +,stack_size{stack_size} +,stack_base{nullptr} +,yc{nullptr} +{ +} + +ctx::ctx::~ctx() +noexcept +{ +} + +void +ctx::ctx::operator()(boost::asio::yield_context yc, + const std::function func) +{ + this->stack_base = reinterpret_cast(__builtin_frame_address(0)); + this->yc = &yc; + ircd::ctx::current = this; + + if(likely(bool(func))) + func(); +} diff --git a/tools/boostrap.sh b/tools/boostrap.sh index b6feee112..ab8f0b267 100755 --- a/tools/boostrap.sh +++ b/tools/boostrap.sh @@ -147,11 +147,25 @@ run git submodule update --init --recursive libs/function run git submodule update --init --recursive libs/function_types run git submodule update --init --recursive libs/iostreams -run ./bootstrap.sh --prefix=$PWD --libdir=$PWD/lib --with-libraries=$BLIBS $BSFLAGS -run ./b2 threading=$BTHREADING variant=$BVARIANT link=$BLINK address-model=64 +run git submodule update --init --recursive libs/coroutine +#run git submodule update --init --recursive libs/coroutine2 +## ASIO does not need coroutine2 at this time, but there is +## some issue with segmented stack support requiring inclusion +## of libs/context... +run git submodule update --init --recursive libs/context +run git submodule update --init --recursive libs/thread +run git submodule update --init --recursive libs/chrono +run git submodule update --init --recursive libs/atomic +run git submodule update --init --recursive libs/ratio +run git submodule update --init --recursive libs/intrusive +run git submodule update --init --recursive libs/tuple +run git submodule update --init --recursive libs/exception +run git submodule update --init --recursive libs/algorithm ### Install should go right into this local submodule repository -run ./b2 install +run ./bootstrap.sh --prefix=$PWD --libdir=$PWD/lib --with-libraries=$BLIBS $BSFLAGS +run ./b2 headers +run ./b2 install threading=$BTHREADING variant=$BVARIANT link=$BLINK address-model=64 warnings=all ### TODO: this shouldn't be necessary. ### XXX: required when boost submodules are fetched and built la carte, but not required