2
0
mirror of https://github.com/boostorg/context.git synced 2026-01-19 04:02:17 +00:00

implementation of fiber::uses_system_stack()

This commit is contained in:
Oliver Kowalke
2018-03-21 12:54:53 +01:00
parent cbd4e42e00
commit 5686c2e75f
7 changed files with 149 additions and 24 deletions

View File

@@ -37,6 +37,7 @@ project boost/context
<toolset>msvc,<link>shared:<define>BOOST_CONTEXT_EXPORT=EXPORT
<toolset>msvc,<link>static:<define>BOOST_CONTEXT_EXPORT=
<link>shared:<define>BOOST_CONTEXT_DYN_LINK=1
<linkflags>"-lunwind"
<define>BOOST_CONTEXT_SOURCE
<threading>multi
: usage-requirements

View File

@@ -23,6 +23,7 @@ project boost/context/example/fiber
<toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack
<toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
<link>static
<linkflags>"-lunwind"
<threading>multi
;
@@ -74,6 +75,10 @@ exe circle
: circle.cpp
;
exe migrateable
: migrateable.cpp
;
#exe backtrace
# : backtrace.cpp
# ;

View File

@@ -0,0 +1,27 @@
// Copyright Oliver Kowalke 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define UNW_LOCAL_ONLY
#include <cstdlib>
#include <iostream>
#include <boost/context/fiber.hpp>
namespace ctx = boost::context;
int main() {
ctx::fiber f{
[](ctx::fiber && m){
std::cout << "fiber `m`: " << std::boolalpha << m.uses_system_stack() << std::endl;
m = std::move( m).resume();
return std::move( m);
}};
std::cout << "fiber `f`: " << std::boolalpha << f.uses_system_stack() << std::endl;
f = std::move( f).resume();
std::cout << "main: done" << std::endl;
return EXIT_SUCCESS;
}

View File

@@ -7,6 +7,8 @@
#ifndef BOOST_CONTEXT_FIBER_H
#define BOOST_CONTEXT_FIBER_H
#define UNW_LOCAL_ONLY
#include <boost/context/detail/config.hpp>
#include <algorithm>
@@ -20,6 +22,8 @@
#include <tuple>
#include <utility>
#include <libunwind.h>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/intrusive_ptr.hpp>
@@ -53,6 +57,22 @@ namespace boost {
namespace context {
namespace detail {
inline
bool fiber_uses_sidestack() {
unw_cursor_t cursor;
unw_context_t context;
unw_getcontext( & context);
unw_init_local( & cursor, & context);
while ( 0 < unw_step( & cursor) );
unw_word_t offset;
char sym[256];
int err = unw_get_proc_name( & cursor, sym, sizeof( sym), & offset);
if ( 0 != err) {
return false;
}
return std::string( sym) == "make_fcontext";
}
inline
transfer_t fiber_unwind( transfer_t t) {
throw forced_unwind( t.fctx);
@@ -74,8 +94,14 @@ void fiber_entry( transfer_t t) noexcept {
BOOST_ASSERT( nullptr != t.fctx);
BOOST_ASSERT( nullptr != rec);
try {
rep:
// jump back to `create_context()`
t = jump_fcontext( t.fctx, nullptr);
// test if stack walk was requested
if ( nullptr != t.data) {
* static_cast< bool * >( t.data) = fiber_uses_sidestack();
goto rep;
}
// start executing
t.fctx = rec->run( t.fctx);
} catch ( forced_unwind const& e) {
@@ -277,27 +303,60 @@ public:
fiber resume() && {
BOOST_ASSERT( nullptr != fctx_);
return { detail::jump_fcontext(
rep:
auto t = detail::jump_fcontext(
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
detail::exchange( fctx_, nullptr),
#else
std::exchange( fctx_, nullptr),
#endif
nullptr).fctx };
nullptr);
if ( nullptr != t.data) {
* static_cast< bool * >( t.data) = detail::fiber_uses_sidestack();
fctx_ = t.fctx;
goto rep;
}
return { t.fctx };
}
template< typename Fn >
fiber resume_with( Fn && fn) && {
BOOST_ASSERT( nullptr != fctx_);
auto p = std::make_tuple( std::forward< Fn >( fn) );
return { detail::ontop_fcontext(
auto t = detail::ontop_fcontext(
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
detail::exchange( fctx_, nullptr),
#else
std::exchange( fctx_, nullptr),
#endif
& p,
detail::fiber_ontop< fiber, Fn >).fctx };
detail::fiber_ontop< fiber, Fn >);
while ( nullptr != t.data) {
* static_cast< bool * >( t.data) = detail::fiber_uses_sidestack();
fctx_ = t.fctx;
t = detail::jump_fcontext(
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
detail::exchange( fctx_, nullptr),
#else
std::exchange( fctx_, nullptr),
#endif
nullptr);
}
return { t.fctx };
}
bool uses_system_stack() {
BOOST_ASSERT( * this);
bool sidestack = false;
auto t = detail::jump_fcontext(
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
detail::exchange( fctx_, nullptr),
#else
std::exchange( fctx_, nullptr),
#endif
& sidestack);
fctx_ = t.fctx;
return ! sidestack;
}
explicit operator bool() const noexcept {

View File

@@ -23,6 +23,7 @@ project boost/context/performance/fiber
<toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack
<toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
<link>static
<linkflags>"-lunwind"
<optimization>speed
<threading>multi
<variant>release

View File

@@ -24,6 +24,7 @@ project boost/context/test
<toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
<link>static
<threading>multi
<linkflags>"-lunwind"
;
@@ -93,26 +94,7 @@ test-suite minimal :
cxx11_rvalue_references
cxx11_template_aliases
cxx11_thread_local
cxx11_variadic_templates ]
: test_fiber_asm ]
[ run test_fiber.cpp :
: :
<conditional>@native-impl
[ requires cxx11_auto_declarations
cxx11_constexpr
cxx11_defaulted_functions
cxx11_final
cxx11_hdr_thread
cxx11_hdr_tuple
cxx11_lambdas
cxx11_noexcept
cxx11_nullptr
cxx11_rvalue_references
cxx11_template_aliases
cxx11_thread_local
cxx11_variadic_templates ]
: test_fiber_native ]
cxx11_variadic_templates ] ]
[ run test_callcc.cpp :
: :

View File

@@ -403,6 +403,55 @@ void test_snprintf() {
}}.resume();
}
void test_use_system_stack() {
{
ctx::fiber f{
[]( ctx::fiber && m) {
BOOST_CHECK( m);
BOOST_CHECK( m.uses_system_stack() );
m = std::move( m).resume();
BOOST_CHECK( m.uses_system_stack() );
return std::move( m);
}};
BOOST_CHECK( f);
BOOST_CHECK( ! f.uses_system_stack() );
f = std::move( f).resume();
BOOST_CHECK( f);
BOOST_CHECK( ! f.uses_system_stack() );
f = std::move( f).resume();
BOOST_CHECK( ! f);
}
{
ctx::fiber f{
[]( ctx::fiber && m) {
BOOST_CHECK( m);
BOOST_CHECK( m.uses_system_stack() );
m = std::move( m).resume();
BOOST_CHECK( m);
BOOST_CHECK( m.uses_system_stack() );
m = std::move( m).resume();
BOOST_CHECK( m);
BOOST_CHECK( m.uses_system_stack() );
return std::move( m);
}};
BOOST_CHECK( f);
BOOST_CHECK( ! f.uses_system_stack() );
f = std::move( f).resume();
BOOST_CHECK( f);
BOOST_CHECK( ! f.uses_system_stack() );
f = std::move( f).resume_with(
[]( ctx::fiber && m) {
BOOST_CHECK( m);
BOOST_CHECK( m.uses_system_stack() );
return std::move( m);
});
BOOST_CHECK( f);
BOOST_CHECK( ! f.uses_system_stack() );
f = std::move( f).resume();
BOOST_CHECK( ! f);
}
}
#ifdef BOOST_WINDOWS
void test_bug12215() {
ctx::fiber{
@@ -430,6 +479,7 @@ boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
test->add( BOOST_TEST_CASE( & test_termination) );
test->add( BOOST_TEST_CASE( & test_sscanf) );
test->add( BOOST_TEST_CASE( & test_snprintf) );
test->add( BOOST_TEST_CASE( & test_use_system_stack) );
#ifdef BOOST_WINDOWS
test->add( BOOST_TEST_CASE( & test_bug12215) );
#endif