summaryrefslogtreecommitdiff
path: root/boost/context
diff options
context:
space:
mode:
Diffstat (limited to 'boost/context')
-rw-r--r--boost/context/all.hpp13
-rw-r--r--boost/context/detail/config.hpp34
-rw-r--r--boost/context/execution_context.hpp307
-rw-r--r--boost/context/fcontext.hpp2
-rw-r--r--boost/context/fixedsize_stack.hpp81
-rw-r--r--boost/context/posix/protected_fixedsize_stack.hpp112
-rw-r--r--boost/context/posix/segmented_stack.hpp81
-rw-r--r--boost/context/protected_fixedsize_stack.hpp13
-rw-r--r--boost/context/segmented_stack.hpp13
-rw-r--r--boost/context/stack_context.hpp67
-rw-r--r--boost/context/stack_traits.hpp42
-rw-r--r--boost/context/windows/protected_fixedsize_stack.hpp93
12 files changed, 846 insertions, 12 deletions
diff --git a/boost/context/all.hpp b/boost/context/all.hpp
index 6bf7e8f190..152f299089 100644
--- a/boost/context/all.hpp
+++ b/boost/context/all.hpp
@@ -1,12 +1,13 @@
-// Copyright Oliver Kowalke 2009.
+// Copyright Oliver Kowalke 2014.
// 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)
-#ifndef BOOST_CONTEXT_ALL_H
-#define BOOST_CONTEXT_ALL_H
-
#include <boost/context/fcontext.hpp>
-
-#endif // BOOST_CONTEXT_ALL_H
+#include <boost/context/fixedsize_stack.hpp>
+#include <boost/context/protected_fixedsize_stack.hpp>
+#include <boost/context/segmented_stack.hpp>
+#include <boost/context/stack_context.hpp>
+#include <boost/context/stack_traits.hpp>
+#include <boost/context/execution_context.hpp>
diff --git a/boost/context/detail/config.hpp b/boost/context/detail/config.hpp
index c30c8f8b84..28edf1f953 100644
--- a/boost/context/detail/config.hpp
+++ b/boost/context/detail/config.hpp
@@ -1,5 +1,5 @@
-// Copyright Oliver Kowalke 2009.
+// Copyright Oliver Kowalke 2014.
// 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)
@@ -37,13 +37,37 @@
#undef BOOST_CONTEXT_CALLDECL
#if (defined(i386) || defined(__i386__) || defined(__i386) \
- || defined(__i486__) || defined(__i586__) || defined(__i686__) \
- || defined(__X86__) || defined(_X86_) || defined(__THW_INTEL__) \
- || defined(__I86__) || defined(__INTEL__) || defined(__IA32__) \
- || defined(_M_IX86) || defined(_I86_)) && defined(BOOST_WINDOWS)
+ || defined(__i486__) || defined(__i586__) || defined(__i686__) \
+ || defined(__X86__) || defined(_X86_) || defined(__THW_INTEL__) \
+ || defined(__I86__) || defined(__INTEL__) || defined(__IA32__) \
+ || defined(_M_IX86) || defined(_I86_)) && defined(BOOST_WINDOWS)
# define BOOST_CONTEXT_CALLDECL __cdecl
#else
# define BOOST_CONTEXT_CALLDECL
#endif
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+# if ! ( (defined(__GNUC__) && __GNUC__ > 3 && __GNUC_MINOR__ > 6) || \
+ (defined(__clang__) && __clang_major__ > 2 && __clang_minor__ > 3) )
+# error "compiler does not support segmented_stack stacks"
+# endif
+# define BOOST_CONTEXT_SEGMENTS 10
+#endif
+
+#undef BOOST_CONTEXT_NO_EXECUTION_CONTEXT
+#if defined( BOOST_NO_CXX11_DECLTYPE) || \
+ defined( BOOST_NO_CXX11_DELETED_FUNCTIONS) || \
+ defined( BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || \
+ defined( BOOST_NO_CXX11_HDR_TUPLE) || \
+ defined( BOOST_NO_CXX11_LAMBDAS) || \
+ defined( BOOST_NO_CXX11_NOEXCEPT) || \
+ defined( BOOST_NO_CXX11_NULLPTR) || \
+ defined( BOOST_NO_CXX11_TEMPLATE_ALIASES) || \
+ defined( BOOST_NO_CXX11_RVALUE_REFERENCES) || \
+ defined( BOOST_NO_CXX11_VARIADIC_MACROS) || \
+ defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
+ defined( BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES)
+# define BOOST_CONTEXT_NO_EXECUTION_CONTEXT
+#endif
+
#endif // BOOST_CONTEXT_DETAIL_CONFIG_H
diff --git a/boost/context/execution_context.hpp b/boost/context/execution_context.hpp
new file mode 100644
index 0000000000..4d809b0c21
--- /dev/null
+++ b/boost/context/execution_context.hpp
@@ -0,0 +1,307 @@
+
+// Copyright Oliver Kowalke 2014.
+// 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)
+
+#ifndef BOOST_CONTEXT_EXECUTION_CONTEXT_H
+#define BOOST_CONTEXT_EXECUTION_CONTEXT_H
+
+#include <boost/context/detail/config.hpp>
+
+#if ! defined(BOOST_CONTEXT_NO_EXECUTION_CONTEXT)
+
+# include <cstddef>
+# include <cstdint>
+# include <cstdlib>
+# include <exception>
+# include <memory>
+# include <tuple>
+# include <utility>
+
+# include <boost/assert.hpp>
+# include <boost/config.hpp>
+# include <boost/context/fcontext.hpp>
+# include <boost/intrusive_ptr.hpp>
+
+# include <boost/context/stack_context.hpp>
+# include <boost/context/segmented_stack.hpp>
+
+# ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+# endif
+
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+extern "C" {
+
+void __splitstack_getcontext( void * [BOOST_CONTEXT_SEGMENTS]);
+
+void __splitstack_setcontext( void * [BOOST_CONTEXT_SEGMENTS]);
+
+}
+# endif
+
+namespace boost {
+namespace context {
+
+struct preallocated {
+ void * sp;
+ std::size_t size;
+ stack_context sctx;
+
+ preallocated( void * sp_, std::size_t size_, stack_context sctx_) noexcept :
+ sp( sp_), size( size_), sctx( sctx_) {
+ }
+};
+
+class BOOST_CONTEXT_DECL execution_context {
+private:
+ struct fcontext {
+ std::size_t use_count;
+ fcontext_t fctx;
+ stack_context sctx;
+
+ // main-context
+ fcontext() noexcept :
+ use_count( 1),
+ fctx( nullptr),
+ sctx() {
+ }
+
+ // worker-context
+ fcontext( fcontext_t fctx_, stack_context const& sctx_) noexcept :
+ use_count( 0),
+ fctx( fctx_),
+ sctx( sctx_) {
+ }
+
+ virtual ~fcontext() noexcept {
+ }
+
+ virtual void deallocate() {
+ }
+
+ virtual void run() noexcept {
+ }
+
+ friend void intrusive_ptr_add_ref( fcontext * ctx) {
+ ++ctx->use_count;
+ }
+
+ friend void intrusive_ptr_release( fcontext * ctx) {
+ BOOST_ASSERT( nullptr != ctx);
+
+ if ( 0 == --ctx->use_count) {
+ ctx->~fcontext();
+ }
+ }
+ };
+
+ template< typename Fn, typename StackAlloc >
+ class worker_fcontext : public fcontext {
+ private:
+ StackAlloc salloc_;
+ Fn fn_;
+
+ static void destroy( worker_fcontext * p) {
+ StackAlloc salloc( p->salloc_);
+ stack_context sctx( p->sctx);
+ p->~worker_fcontext();
+ salloc.deallocate( sctx);
+ }
+
+ public:
+ explicit worker_fcontext( stack_context sctx, StackAlloc const& salloc, fcontext_t fctx, Fn && fn) noexcept :
+ fcontext( fctx, sctx),
+ salloc_( salloc),
+ fn_( std::forward< Fn >( fn) ) {
+ }
+
+ void deallocate() override final {
+ destroy( this);
+ }
+
+ void run() noexcept override final {
+ fn_();
+ }
+ };
+
+ static void entry_func( intptr_t p) noexcept {
+ BOOST_ASSERT( 0 != p);
+
+ fcontext * bp( reinterpret_cast< fcontext * >( p) );
+ BOOST_ASSERT( nullptr != bp);
+
+ bp->run();
+ }
+
+ typedef boost::intrusive_ptr< fcontext > ptr_t;
+
+ thread_local static fcontext main_ctx_;
+ thread_local static ptr_t current_ctx_;
+
+ boost::intrusive_ptr< fcontext > ptr_;
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ bool use_segmented_stack_ = false;
+# endif
+
+ template< typename StackAlloc, typename Fn >
+ static fcontext * create_context( StackAlloc salloc, Fn && fn) {
+ typedef worker_fcontext< Fn, StackAlloc > func_t;
+
+ stack_context sctx( salloc.allocate() );
+ // reserve space for control structure
+ std::size_t size = sctx.size - sizeof( func_t);
+ void * sp = static_cast< char * >( sctx.sp) - sizeof( func_t);
+#if 0
+ constexpr std::size_t func_alignment = 64; // alignof( func_t);
+ constexpr std::size_t func_size = sizeof( func_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
+ // align sp pointer
+ sp = std::align( func_alignment, func_size, sp, func_size + func_alignment);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ fcontext_t fctx = make_fcontext( sp, size, & execution_context::entry_func);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on fast-context stack
+ return new ( sp) func_t( sctx, salloc, fctx, std::forward< Fn >( fn) );
+ }
+
+ template< typename StackAlloc, typename Fn >
+ static fcontext * create_context( preallocated palloc, StackAlloc salloc, Fn && fn) {
+ typedef worker_fcontext< Fn, StackAlloc > func_t;
+
+ // reserve space for control structure
+ std::size_t size = palloc.size - sizeof( func_t);
+ void * sp = static_cast< char * >( palloc.sp) - sizeof( func_t);
+#if 0
+ constexpr std::size_t func_alignment = 64; // alignof( func_t);
+ constexpr std::size_t func_size = sizeof( func_t);
+ // reserve space on stack
+ void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
+ // align sp pointer
+ sp = std::align( func_alignment, func_size, sp, func_size + func_alignment);
+ BOOST_ASSERT( nullptr != sp);
+ // calculate remaining size
+ std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
+#endif
+ // create fast-context
+ fcontext_t fctx = make_fcontext( sp, size, & execution_context::entry_func);
+ BOOST_ASSERT( nullptr != fctx);
+ // placment new for control structure on fast-context stack
+ return new ( sp) func_t( palloc.sctx, salloc, fctx, std::forward< Fn >( fn) );
+ }
+
+ template< typename StackAlloc, typename Fn, typename Tpl, std::size_t ... I >
+ static fcontext * create_worker_fcontext( StackAlloc salloc,
+ Fn && fn_, Tpl && tpl_,
+ std::index_sequence< I ... >) {
+ return create_context( salloc,
+ [fn=std::forward< Fn >( fn_),tpl=std::forward< Tpl >( tpl_)] () mutable {
+ try {
+ fn(
+ // std::tuple_element<> does not perfect forwarding
+ std::forward< decltype( std::get< I >( std::declval< Tpl >() ) ) >(
+ std::get< I >( std::forward< Tpl >( tpl) ) ) ... );
+ } catch (...) {
+ std::terminate();
+ }
+ });
+ }
+
+ template< typename StackAlloc, typename Fn, typename Tpl, std::size_t ... I >
+ static fcontext * create_worker_fcontext( preallocated palloc, StackAlloc salloc,
+ Fn && fn_, Tpl && tpl_,
+ std::index_sequence< I ... >) {
+ return create_context( palloc, salloc,
+ [fn=std::forward< Fn >( fn_),tpl=std::forward< Tpl >( tpl_)] () mutable {
+ try {
+ fn(
+ // std::tuple_element<> does not perfect forwarding
+ std::forward< decltype( std::get< I >( std::declval< Tpl >() ) ) >(
+ std::get< I >( std::forward< Tpl >( tpl) ) ) ... );
+ } catch (...) {
+ std::terminate();
+ }
+ });
+ }
+
+ execution_context() :
+ ptr_( current_ctx_) {
+ }
+
+public:
+ static execution_context current() noexcept {
+ return execution_context();
+ }
+
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ template< typename Fn, typename ... Args >
+ explicit execution_context( segmented_stack salloc, Fn && fn, Args && ... args) :
+ ptr_( create_worker_fcontext( salloc,
+ std::forward< Fn >( fn),
+ std::make_tuple( std::forward< Args >( args) ... ),
+ std::index_sequence_for< Args ... >() ) ),
+ use_segmented_stack_( true) {
+ }
+
+ template< typename Fn, typename ... Args >
+ explicit execution_context( preallocated palloc, segmented_stack salloc, Fn && fn, Args && ... args) :
+ ptr_( create_worker_fcontext( palloc, salloc,
+ std::forward< Fn >( fn),
+ std::make_tuple( std::forward< Args >( args) ... ),
+ std::index_sequence_for< Args ... >() ) ),
+ use_segmented_stack_( true) {
+ }
+# endif
+
+ template< typename StackAlloc, typename Fn, typename ... Args >
+ explicit execution_context( StackAlloc salloc, Fn && fn, Args && ... args) :
+ ptr_( create_worker_fcontext( salloc,
+ std::forward< Fn >( fn),
+ std::make_tuple( std::forward< Args >( args) ... ),
+ std::index_sequence_for< Args ... >() ) ) {
+ }
+
+ template< typename StackAlloc, typename Fn, typename ... Args >
+ explicit execution_context( preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args) :
+ ptr_( create_worker_fcontext( palloc, salloc,
+ std::forward< Fn >( fn),
+ std::make_tuple( std::forward< Args >( args) ... ),
+ std::index_sequence_for< Args ... >() ) ) {
+ }
+
+ void resume( bool preserve_fpu = false) noexcept {
+ fcontext * old_ctx( current_ctx_.get() );
+ fcontext * new_ctx( ptr_.get() );
+ current_ctx_ = ptr_;
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ if ( use_segmented_stack_) {
+ __splitstack_getcontext( old_ctx->sctx.segments_ctx);
+ __splitstack_setcontext( new_ctx->sctx.segments_ctx);
+
+ jump_fcontext( & old_ctx->fctx, new_ctx->fctx, reinterpret_cast< intptr_t >( new_ctx), preserve_fpu);
+
+ __splitstack_setcontext( old_ctx->sctx.segments_ctx);
+ } else {
+ jump_fcontext( & old_ctx->fctx, new_ctx->fctx, reinterpret_cast< intptr_t >( new_ctx), preserve_fpu);
+ }
+# else
+ jump_fcontext( & old_ctx->fctx, new_ctx->fctx, reinterpret_cast< intptr_t >( new_ctx), preserve_fpu);
+# endif
+ }
+};
+
+}}
+
+# ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+# endif
+
+#endif
+
+#endif // BOOST_CONTEXT_EXECUTION_CONTEXT_H
diff --git a/boost/context/fcontext.hpp b/boost/context/fcontext.hpp
index d054df290c..2ebcd46e38 100644
--- a/boost/context/fcontext.hpp
+++ b/boost/context/fcontext.hpp
@@ -31,7 +31,7 @@ typedef void* fcontext_t;
extern "C" BOOST_CONTEXT_DECL
intptr_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t * ofc, fcontext_t nfc,
- intptr_t vp, bool preserve_fpu = true);
+ intptr_t vp, bool preserve_fpu = false);
extern "C" BOOST_CONTEXT_DECL
fcontext_t BOOST_CONTEXT_CALLDECL make_fcontext( void * sp, std::size_t size, void (* fn)( intptr_t) );
diff --git a/boost/context/fixedsize_stack.hpp b/boost/context/fixedsize_stack.hpp
new file mode 100644
index 0000000000..5acb5f47c0
--- /dev/null
+++ b/boost/context/fixedsize_stack.hpp
@@ -0,0 +1,81 @@
+
+// Copyright Oliver Kowalke 2014.
+// 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)
+
+#ifndef BOOST_CONTEXT_FIXEDSIZE_H
+#define BOOST_CONTEXT_FIXEDSIZE_H
+
+#include <cstddef>
+#include <cstdlib>
+#include <new>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+#include <boost/context/stack_context.hpp>
+#include <boost/context/stack_traits.hpp>
+
+#if defined(BOOST_USE_VALGRIND)
+#include <valgrind/valgrind.h>
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+
+template< typename traitsT >
+class basic_fixedsize_stack {
+private:
+ std::size_t size_;
+
+public:
+ typedef traitsT traits_type;
+
+ basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) :
+ size_( size) {
+ BOOST_ASSERT( traits_type::minimum_size() <= size_);
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
+ }
+
+ stack_context allocate() {
+ void * vp = std::malloc( size_);
+ if ( ! vp) throw std::bad_alloc();
+
+ stack_context sctx;
+ sctx.size = size_;
+ sctx.sp = static_cast< char * >( vp) + sctx.size;
+#if defined(BOOST_USE_VALGRIND)
+ sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp);
+#endif
+ return sctx;
+ }
+
+ void deallocate( stack_context & sctx) {
+ BOOST_ASSERT( sctx.sp);
+ BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
+
+#if defined(BOOST_USE_VALGRIND)
+ VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
+#endif
+
+ void * vp = static_cast< char * >( sctx.sp) - sctx.size;
+ std::free( vp);
+ }
+};
+
+typedef basic_fixedsize_stack< stack_traits > fixedsize_stack;
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_FIXEDSIZE_H
diff --git a/boost/context/posix/protected_fixedsize_stack.hpp b/boost/context/posix/protected_fixedsize_stack.hpp
new file mode 100644
index 0000000000..c7e09439fc
--- /dev/null
+++ b/boost/context/posix/protected_fixedsize_stack.hpp
@@ -0,0 +1,112 @@
+
+// Copyright Oliver Kowalke 2014.
+// 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)
+
+#ifndef BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H
+#define BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H
+
+extern "C" {
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+}
+
+#include <cmath>
+#include <cstddef>
+#include <new>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+#include <boost/context/stack_context.hpp>
+#include <boost/context/stack_traits.hpp>
+
+#if defined(BOOST_USE_VALGRIND)
+#include <valgrind/valgrind.h>
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+
+template< typename traitsT >
+class basic_protected_fixedsize_stack {
+private:
+ std::size_t size_;
+
+public:
+ typedef traitsT traits_type;
+
+ basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) :
+ size_( size) {
+ BOOST_ASSERT( traits_type::minimum_size() <= size_);
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
+ }
+
+ stack_context allocate() {
+ // page at bottom will be used as guard-page
+ const std::size_t pages(
+ static_cast< std::size_t >(
+ std::floor(
+ static_cast< float >( size_) / traits_type::page_size() ) ) );
+ BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
+ const std::size_t size__( pages * traits_type::page_size() );
+ BOOST_ASSERT( 0 < size_ && 0 < size__);
+ BOOST_ASSERT( size__ <= size_);
+
+ // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
+#if defined(MAP_ANON)
+ void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+#else
+ void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+#endif
+ if ( MAP_FAILED == vp) throw std::bad_alloc();
+
+ // conforming to POSIX.1-2001
+#if defined(BOOST_DISABLE_ASSERTS)
+ ::mprotect( vp, traits_type::page_size(), PROT_NONE);
+#else
+ const int result( ::mprotect( vp, traits_type::page_size(), PROT_NONE) );
+ BOOST_ASSERT( 0 == result);
+#endif
+
+ stack_context sctx;
+ sctx.size = size__;
+ sctx.sp = static_cast< char * >( vp) + sctx.size;
+#if defined(BOOST_USE_VALGRIND)
+ sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp);
+#endif
+ return sctx;
+ }
+
+ void deallocate( stack_context & sctx) {
+ BOOST_ASSERT( sctx.sp);
+ BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
+
+#if defined(BOOST_USE_VALGRIND)
+ VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
+#endif
+
+ void * vp = static_cast< char * >( sctx.sp) - sctx.size;
+ // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
+ ::munmap( vp, sctx.size);
+ }
+};
+
+typedef basic_protected_fixedsize_stack< stack_traits > protected_fixedsize_stack;
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H
diff --git a/boost/context/posix/segmented_stack.hpp b/boost/context/posix/segmented_stack.hpp
new file mode 100644
index 0000000000..f4a32d7394
--- /dev/null
+++ b/boost/context/posix/segmented_stack.hpp
@@ -0,0 +1,81 @@
+
+// Copyright Oliver Kowalke 2014.
+// 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)
+
+#ifndef BOOST_CONTEXT_SEGMENTED_H
+#define BOOST_CONTEXT_SEGMENTED_H
+
+#include <cstddef>
+#include <new>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+#include <boost/context/stack_context.hpp>
+#include <boost/context/stack_traits.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+// forward declaration for splitstack-functions defined in libgcc
+extern "C" {
+void *__splitstack_makecontext( std::size_t,
+ void * [BOOST_CONTEXT_SEGMENTS],
+ std::size_t *);
+
+void __splitstack_releasecontext( void * [BOOST_CONTEXT_SEGMENTS]);
+
+void __splitstack_resetcontext( void * [BOOST_CONTEXT_SEGMENTS]);
+
+void __splitstack_block_signals_context( void * [BOOST_CONTEXT_SEGMENTS],
+ int * new_value, int * old_value);
+}
+
+namespace boost {
+namespace context {
+
+template< typename traitsT >
+class basic_segmented_stack {
+private:
+ std::size_t size_;
+
+public:
+ typedef traitsT traits_type;
+
+ basic_segmented_stack( std::size_t size = traits_type::default_size() ) :
+ size_( size) {
+ BOOST_ASSERT( traits_type::minimum_size() <= size_);
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
+ }
+
+ stack_context allocate() {
+ stack_context sctx;
+ void * vp = __splitstack_makecontext( size_, sctx.segments_ctx, & sctx.size);
+ if ( ! vp) throw std::bad_alloc();
+
+ // sctx.size is already filled by __splitstack_makecontext
+ sctx.sp = static_cast< char * >( vp) + sctx.size;
+
+ int off = 0;
+ __splitstack_block_signals_context( sctx.segments_ctx, & off, 0);
+
+ return sctx;
+ }
+
+ void deallocate( stack_context & sctx) {
+ __splitstack_releasecontext( sctx.segments_ctx);
+ }
+};
+
+typedef basic_segmented_stack< stack_traits > segmented_stack;
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_SEGMENTED_H
diff --git a/boost/context/protected_fixedsize_stack.hpp b/boost/context/protected_fixedsize_stack.hpp
new file mode 100644
index 0000000000..a05aa73fe9
--- /dev/null
+++ b/boost/context/protected_fixedsize_stack.hpp
@@ -0,0 +1,13 @@
+
+// Copyright Oliver Kowalke 2014.
+// 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)
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_WINDOWS)
+# include <boost/context/windows/protected_fixedsize_stack.hpp>
+#else
+# include <boost/context/posix/protected_fixedsize_stack.hpp>
+#endif
diff --git a/boost/context/segmented_stack.hpp b/boost/context/segmented_stack.hpp
new file mode 100644
index 0000000000..88e3e6a61f
--- /dev/null
+++ b/boost/context/segmented_stack.hpp
@@ -0,0 +1,13 @@
+
+// Copyright Oliver Kowalke 2014.
+// 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)
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+# if ! defined(BOOST_WINDOWS)
+# include <boost/context/posix/segmented_stack.hpp>
+# endif
+#endif
diff --git a/boost/context/stack_context.hpp b/boost/context/stack_context.hpp
new file mode 100644
index 0000000000..48863b3bc8
--- /dev/null
+++ b/boost/context/stack_context.hpp
@@ -0,0 +1,67 @@
+
+// Copyright Oliver Kowalke 2014.
+// 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)
+
+#ifndef BOOST_CONTEXT_STACK_CONTEXT_H
+#define BOOST_CONTEXT_STACK_CONTEXT_H
+
+#include <cstddef>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+struct stack_context {
+ typedef void * segments_context[BOOST_CONTEXT_SEGMENTS];
+
+ std::size_t size;
+ void * sp;
+ segments_context segments_ctx;
+#if defined(BOOST_USE_VALGRIND)
+ unsigned valgrind_stack_id;
+#endif
+
+ stack_context() :
+ size( 0),
+ sp( 0),
+ segments_ctx()
+#if defined(BOOST_USE_VALGRIND)
+ , valgrind_stack_id( 0)
+#endif
+ {}
+};
+#else
+struct stack_context {
+ std::size_t size;
+ void * sp;
+#if defined(BOOST_USE_VALGRIND)
+ unsigned valgrind_stack_id;
+#endif
+
+ stack_context() :
+ size( 0),
+ sp( 0)
+#if defined(BOOST_USE_VALGRIND)
+ , valgrind_stack_id( 0)
+#endif
+ {}
+};
+#endif
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_STACK_CONTEXT_H
diff --git a/boost/context/stack_traits.hpp b/boost/context/stack_traits.hpp
new file mode 100644
index 0000000000..9b8a70636d
--- /dev/null
+++ b/boost/context/stack_traits.hpp
@@ -0,0 +1,42 @@
+
+// Copyright Oliver Kowalke 2014.
+// 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)
+
+#ifndef BOOST_CONTEXT_STACK_TRAITS_H
+#define BOOST_CONTEXT_STACK_TRAITS_H
+
+#include <cstddef>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+
+struct BOOST_CONTEXT_DECL stack_traits
+{
+ static bool is_unbounded() BOOST_NOEXCEPT;
+
+ static std::size_t page_size() BOOST_NOEXCEPT;
+
+ static std::size_t default_size() BOOST_NOEXCEPT;
+
+ static std::size_t minimum_size() BOOST_NOEXCEPT;
+
+ static std::size_t maximum_size() BOOST_NOEXCEPT;
+};
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_STACK_TRAITS_H
diff --git a/boost/context/windows/protected_fixedsize_stack.hpp b/boost/context/windows/protected_fixedsize_stack.hpp
new file mode 100644
index 0000000000..478c8c4ae1
--- /dev/null
+++ b/boost/context/windows/protected_fixedsize_stack.hpp
@@ -0,0 +1,93 @@
+
+// Copyright Oliver Kowalke 2014.
+// 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)
+
+#ifndef BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H
+#define BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H
+
+extern "C" {
+#include <windows.h>
+}
+
+#include <cmath>
+#include <cstddef>
+#include <new>
+
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+#include <boost/context/stack_context.hpp>
+#include <boost/context/stack_traits.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+
+template< typename traitsT >
+class basic_protected_fixedsize_stack {
+private:
+ std::size_t size_;
+
+public:
+ typedef traitsT traits_type;
+
+ basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) :
+ size_( size) {
+ BOOST_ASSERT( traits_type::minimum_size() <= size_);
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
+ }
+
+ stack_context allocate() {
+ // page at bottom will be used as guard-page
+ const std::size_t pages(
+ static_cast< std::size_t >(
+ std::floor(
+ static_cast< float >( size_) / traits_type::page_size() ) ) );
+ BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
+ const std::size_t size__( pages * traits_type::page_size() );
+ BOOST_ASSERT( 0 < size_ && 0 < size__);
+ BOOST_ASSERT( size__ <= size_);
+
+ void * vp = ::VirtualAlloc( 0, size__, MEM_COMMIT, PAGE_READWRITE);
+ if ( ! vp) throw std::bad_alloc();
+
+ DWORD old_options;
+#if defined(BOOST_DISABLE_ASSERTS)
+ ::VirtualProtect(
+ vp, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
+#else
+ const BOOL result = ::VirtualProtect(
+ vp, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
+ BOOST_ASSERT( FALSE != result);
+#endif
+
+ stack_context sctx;
+ sctx.size = size__;
+ sctx.sp = static_cast< char * >( vp) + sctx.size;
+ return sctx;
+ }
+
+ void deallocate( stack_context & sctx) {
+ BOOST_ASSERT( sctx.sp);
+ BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
+
+ void * vp = static_cast< char * >( sctx.sp) - sctx.size;
+ ::VirtualFree( vp, 0, MEM_RELEASE);
+ }
+};
+
+typedef basic_protected_fixedsize_stack< stack_traits > protected_fixedsize_stack;
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H