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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
# ;
|
||||
|
||||
27
example/fiber/migrateable.cpp
Normal file
27
example/fiber/migrateable.cpp
Normal 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;
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 :
|
||||
: :
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user