From dbfeda223df4f36c9036fdbb23feff81b8650878 Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Wed, 14 Nov 2012 17:30:45 +0000 Subject: [PATCH] context: simple_stack_allocator moved to examples directory, guarded_stack_allocator removed [SVN r81346] --- build/Jamfile.v2 | 4 - doc/context.qbk | 1 - doc/stack.qbk | 188 +----------------- example/exit.cpp | 18 +- example/jump.cpp | 22 +- .../simple_stack_allocator.hpp | 0 example/transfer.cpp | 15 +- include/boost/context/all.hpp | 3 - .../boost/context/guarded_stack_allocator.hpp | 55 ----- include/boost/context/utils.hpp | 41 ---- performance/performance.cpp | 32 +-- src/guarded_stack_allocator_posix.cpp | 152 -------------- src/guarded_stack_allocator_windows.cpp | 156 --------------- src/utils_posix.cpp | 39 ---- src/utils_windows.cpp | 48 ----- test/test_context.cpp | 88 ++++---- 16 files changed, 107 insertions(+), 755 deletions(-) rename {include/boost/context => example}/simple_stack_allocator.hpp (100%) delete mode 100644 include/boost/context/guarded_stack_allocator.hpp delete mode 100644 include/boost/context/utils.hpp delete mode 100644 src/guarded_stack_allocator_posix.cpp delete mode 100644 src/guarded_stack_allocator_windows.cpp delete mode 100644 src/utils_posix.cpp delete mode 100644 src/utils_windows.cpp diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 3116cca..a3c0187 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -429,15 +429,11 @@ alias select_asm_context_sources alias context_sources : fcontext.cpp seh.cpp - guarded_stack_allocator_windows.cpp - utils_windows.cpp : windows ; alias context_sources : fcontext.cpp - guarded_stack_allocator_posix.cpp - utils_posix.cpp ; explicit context_sources ; diff --git a/doc/context.qbk b/doc/context.qbk index a47e5ac..dde293a 100644 --- a/doc/context.qbk +++ b/doc/context.qbk @@ -41,7 +41,6 @@ [def __threads__ ['threads]] [def __tls__ ['thread-local storage]] [def __stack_allocator__ ['StackAllocator]] -[def __stack_allocator_concept__ ['StackAllocator concept]] [def __fcontext__ ['fcontext_t]] [def __ucontext__ ['ucontext_t]] diff --git a/doc/stack.qbk b/doc/stack.qbk index 497cec7..5d179a7 100644 --- a/doc/stack.qbk +++ b/doc/stack.qbk @@ -1,5 +1,4 @@ -[/ - Copyright Oliver Kowalke 2009. +[/ Copyright Oliver Kowalke 2009. 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 @@ -8,190 +7,19 @@ [section:stack Stack allocation] A __fcontext__ requires a stack which will be allocated/deallocated -by a __stack_allocator__. -__boost_context__ provides the default implementation `stack_allocator` but a -customized __stack_allocator__ can be used instead. +by a __stack_allocator__ (examples contain an implementation +of [@boost:/libs/context/example/simple_stack_allocator.hpp +simple_stack_allocator]). -[heading __stack_allocator_concept__] -A __stack_allocator__ must satisfy the __stack_allocator_concept__ requirements -shown in the following table, in which `a` is an object of a -__stack_allocator__ type, `p` is a `void *`, and `s` is a `std::size_t`: - -[table - [[expression][return type][notes]] - [ - [`a.allocate( s)`] - [`void *`] - [returns a pointer to `s` bytes allocated from the stack] - ] - [ - [`a.deallocate( p, s)`] - [`void`] - [deallocates `s` bytes of memory beginning at `p`, - a pointer previously returned by `a.allocate()`] - ] -] - -[important The implementation of `allocate()` might include logic to protect +[note The implementation of a __stack_allocator__ might include logic to protect against exceeding the context's available stack size rather than leaving it as undefined behaviour.] -[important Calling `deallocate()` with a pointer not returned by `allocate()` -results in undefined behaviour.] - [note The stack is not required to be aligned; alignment takes place inside -`make_fcontext()`.] +__make_fcontext__.] -[note Depending on the architecture `allocate()` returns an address from the -top of the stack (growing downwards) or the bottom of the stack (growing +[note Depending on the architecture __stack_allocator__ returns an address from +the top of the stack (grows downwards) or the bottom of the stack (grows upwards).] - -[section:guarded_stack_allocator Class `guarded_stack_allocator`] - -__boost_context__ provides the class `guarded_stack_allocator` which models -the __stack_allocator_concept__ concept. -It appends a __guard_page__ at the end of each stack to protect against exceeding -the stack. If the guard page is accessed (read or write operation) a -segmentation fault/access violation is generated by the operating system. - -[note The appended `guard page` is [*not] mapped to physical memory, only -virtual addresses are used.] - - class guarded_stack_allocator - { - static bool is_stack_unbound(); - - static std::size_t maximum_stacksize(); - - static std::size_t default_stacksize(); - - static std::size_t minimum_stacksize(); - - void * allocate( std::size_t size); - - void deallocate( void * sp, std::size_t size); - } - -[heading `static bool is_stack_unbound()`] -[variablelist -[[Returns:] [Returns `true` if the environment defines no limit for the size of a stack.]] -] - -[heading `static std::size_t maximum_stacksize()`] -[variablelist -[[Preconditions:] [`is_stack_unbound()` returns `false`.]] -[[Returns:] [Returns the maximum size in bytes of stack defined by the environment.]] -] - -[heading `static std::size_t default_stacksize()`] -[variablelist -[[Returns:] [Returns a default stack size, which may be platform specific. -If the stack is unbound then the present implementation returns the maximum of -`64 kB` and `minimum_stacksize()`.]] -] - -[heading `static std::size_t minimum_stacksize()`] -[variablelist -[[Returns:] [Returns the minimum size in bytes of stack defined by the -environment (Win32 4kB/Win64 8kB, defined by rlimit on POSIX).]] -] - -[heading `void * allocate( std::size_t size)`] -[variablelist -[[Preconditions:] [`minimum_stacksize() > size` and -`! is_stack_unbound() && ( maximum_stacksize() < size)`.]] -[[Effects:] [Allocates memory of `size` Bytes and appends one guard page at the -end of the allocated memory.]] -[[Returns:] [Returns pointer to the start address of the new stack. Depending -on the architecture the stack grows downwards/upwards the returned address is -the highest/lowest address of the stack.]] -] - -[heading `void deallocate( void * sp, std::size_t size)`] -[variablelist -[[Preconditions:] [`sp` is valid, `minimum_stacksize() > size` and -`! is_stack_unbound() && ( maximum_stacksize() < size)`.]] -[[Effects:] [Deallocates the stack space.]] -] - -[endsect] - - -[section:simple_stack_allocator Template `simple_stack_allocator< size_t, size_t, size_t >`] - -__boost_context__ provides the class `simple_stack_allocator` which models -the __stack_allocator_concept__ concept. The template arguments define the -limits for the stack size. -The class simply allocates memory on the heap via `calloc()` - in contrast to -`guarded_stack_allocator` no guard page is appended. - -[important The user is responsible for valid stack limits (e.g. maximum, minimum -and default stacksize.] - - template< size_t Max, size_t Default, size_t Min > - class simple_stack_allocator - { - static std::size_t maximum_stacksize(); - - static std::size_t default_stacksize(); - - static std::size_t minimum_stacksize(); - - void * allocate( std::size_t size); - - void deallocate( void * sp, std::size_t size); - } - -[heading `static std::size_t maximum_stacksize()`] -[variablelist -[[Returns:] [Returns the maximum size in bytes of stack defined by the first -tempalte argument.]] -] - -[heading `static std::size_t default_stacksize()`] -[variablelist -[[Returns:] [Returns a default stack size in bytes defined by the second -template argument.]] -] - -[heading `static std::size_t minimum_stacksize()`] -[variablelist -[[Returns:] [Returns the minimum size in bytes of stack defined by the -third template argument.]] -] - -[heading `void * allocate( std::size_t size)`] -[variablelist -[[Preconditions:] [`minimum_stacksize() > size` and -`maximum_stacksize() < size`.]] -[[Effects:] [Allocates memory of `size` bytes (memory is set to NULL).]] -[[Returns:] [Returns pointer to the start address of the new stack. Depending -on the architecture the stack grows downwards/upwards the returned address is -the highest/lowest address of the stack.]] -] - -[heading `void deallocate( void * sp, std::size_t size)`] -[variablelist -[[Preconditions:] [`sp` is valid, `minimum_stacksize() > size` and -`maximum_stacksize() < size`.]] -[[Effects:] [Deallocates the stack space.]] -] - -[endsect] - - -[section:pagesize Free function `pagesize()`] - - std::size_t pagesize(); - -[heading `std::size_t pagesize()`] -[variablelist -[[Returns:] [Returns the size of a page in bytes.]] -] - -This function - -[endsect] - [endsect] diff --git a/example/exit.cpp b/example/exit.cpp index 2feb818..b061bfd 100644 --- a/example/exit.cpp +++ b/example/exit.cpp @@ -12,8 +12,16 @@ #include #include +#include "simple_stack_allocator.hpp" + namespace ctx = boost::context; +typedef ctx::simple_stack_allocator< + 8 * 1024 * 1024, // 8MB + 64 * 1024, // 64kB + 8 * 1024 // 8kB +> stack_allocator; + ctx::fcontext_t * fc1; ctx::fcontext_t * fc2; @@ -36,13 +44,13 @@ void f2( intptr_t) int main( int argc, char * argv[]) { ctx::fcontext_t fcm; - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; - void * sp1 = alloc.allocate(ctx::guarded_stack_allocator::default_stacksize()); - fc1 = ctx::make_fcontext( sp1, ctx::guarded_stack_allocator::default_stacksize(), f1); + void * sp1 = alloc.allocate( stack_allocator::default_stacksize()); + fc1 = ctx::make_fcontext( sp1, stack_allocator::default_stacksize(), f1); - void * sp2 = alloc.allocate(ctx::guarded_stack_allocator::default_stacksize()); - fc2 = ctx::make_fcontext( sp2, ctx::guarded_stack_allocator::default_stacksize(), f2); + void * sp2 = alloc.allocate( stack_allocator::default_stacksize()); + fc2 = ctx::make_fcontext( sp2, stack_allocator::default_stacksize(), f2); std::cout << "main: call start_fcontext( & fcm, fc1, 0)" << std::endl; ctx::jump_fcontext( & fcm, fc1, 0); diff --git a/example/jump.cpp b/example/jump.cpp index 57cb8c2..d43e1a6 100644 --- a/example/jump.cpp +++ b/example/jump.cpp @@ -12,8 +12,16 @@ #include #include +#include "simple_stack_allocator.hpp" + namespace ctx = boost::context; +typedef ctx::simple_stack_allocator< + 8 * 1024 * 1024, // 8MB + 64 * 1024, // 64kB + 8 * 1024 // 8kB +> stack_allocator; + ctx::fcontext_t fcm; ctx::fcontext_t * fc1 = 0; ctx::fcontext_t * fc2 = 0; @@ -37,21 +45,21 @@ void f2( intptr_t) int main( int argc, char * argv[]) { - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; - void * base1 = alloc.allocate(ctx::guarded_stack_allocator::default_stacksize()); + void * base1 = alloc.allocate( stack_allocator::default_stacksize()); BOOST_ASSERT( base1); - fc1 = ctx::make_fcontext( base1, ctx::guarded_stack_allocator::default_stacksize(), f1); + fc1 = ctx::make_fcontext( base1, stack_allocator::default_stacksize(), f1); BOOST_ASSERT( fc1); BOOST_ASSERT( base1 == fc1->fc_stack.sp); - BOOST_ASSERT( ctx::guarded_stack_allocator::default_stacksize() == fc1->fc_stack.size); + BOOST_ASSERT( stack_allocator::default_stacksize() == fc1->fc_stack.size); - void * base2 = alloc.allocate(ctx::guarded_stack_allocator::default_stacksize()); + void * base2 = alloc.allocate( stack_allocator::default_stacksize()); BOOST_ASSERT( base2); - fc2 = ctx::make_fcontext( base2, ctx::guarded_stack_allocator::default_stacksize(), f2); + fc2 = ctx::make_fcontext( base2, stack_allocator::default_stacksize(), f2); BOOST_ASSERT( fc2); BOOST_ASSERT( base2 == fc2->fc_stack.sp); - BOOST_ASSERT( ctx::guarded_stack_allocator::default_stacksize() == fc2->fc_stack.size); + BOOST_ASSERT( stack_allocator::default_stacksize() == fc2->fc_stack.size); std::cout << "main: call start_fcontext( & fcm, fc1, 0)" << std::endl; ctx::jump_fcontext( & fcm, fc1, 0); diff --git a/include/boost/context/simple_stack_allocator.hpp b/example/simple_stack_allocator.hpp similarity index 100% rename from include/boost/context/simple_stack_allocator.hpp rename to example/simple_stack_allocator.hpp diff --git a/example/transfer.cpp b/example/transfer.cpp index 2e2deb4..5aac4c9 100644 --- a/example/transfer.cpp +++ b/example/transfer.cpp @@ -13,8 +13,16 @@ #include #include +#include "simple_stack_allocator.hpp" + namespace ctx = boost::context; +typedef ctx::simple_stack_allocator< + 8 * 1024 * 1024, // 8MB + 64 * 1024, // 64kB + 8 * 1024 // 8kB +> stack_allocator; + ctx::fcontext_t fcm; ctx::fcontext_t * fc1; @@ -31,11 +39,10 @@ void f1( intptr_t param) int main( int argc, char * argv[]) { - typedef ctx::simple_stack_allocator< 256 * 1024, 64 * 1024, 8 * 1024 > alloc_t; - alloc_t alloc; + stack_allocator alloc; - void * sp = alloc.allocate(alloc_t::default_stacksize()); - fc1 = ctx::make_fcontext( sp, alloc_t::default_stacksize(), f1); + void * sp = alloc.allocate( stack_allocator::default_stacksize() ); + fc1 = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f1); pair_t p( std::make_pair( 2, 7) ); int res = ( int) ctx::jump_fcontext( & fcm, fc1, ( intptr_t) & p); diff --git a/include/boost/context/all.hpp b/include/boost/context/all.hpp index cbb63af..6bf7e8f 100644 --- a/include/boost/context/all.hpp +++ b/include/boost/context/all.hpp @@ -8,8 +8,5 @@ #define BOOST_CONTEXT_ALL_H #include -#include -#include -#include #endif // BOOST_CONTEXT_ALL_H diff --git a/include/boost/context/guarded_stack_allocator.hpp b/include/boost/context/guarded_stack_allocator.hpp deleted file mode 100644 index 92cf323..0000000 --- a/include/boost/context/guarded_stack_allocator.hpp +++ /dev/null @@ -1,55 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// 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_GUARDED_STACK_ALLOCATOR_H -#define BOOST_CONTEXT_GUARDED_STACK_ALLOCATOR_H - -#include - -#if ! defined (BOOST_WINDOWS) -extern "C" { -#include -} -#endif - -//#if defined (BOOST_WINDOWS) || _POSIX_C_SOURCE >= 200112L - -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace context { - -class BOOST_CONTEXT_DECL guarded_stack_allocator -{ -public: - static bool is_stack_unbound(); - - static std::size_t default_stacksize(); - - static std::size_t minimum_stacksize(); - - static std::size_t maximum_stacksize(); - - void * allocate( std::size_t) const; - - void deallocate( void *, std::size_t) const; -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -//#endif - -#endif // BOOST_CONTEXT_GUARDED_STACK_ALLOCATOR_H diff --git a/include/boost/context/utils.hpp b/include/boost/context/utils.hpp deleted file mode 100644 index 4b6a2bc..0000000 --- a/include/boost/context/utils.hpp +++ /dev/null @@ -1,41 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// 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_UTILS_H -#define BOOST_CONTEXT_UTILS_H - -#include - -#if ! defined (BOOST_WINDOWS) -extern "C" { -#include -} -#endif - -//#if defined (BOOST_WINDOWS) || _POSIX_C_SOURCE >= 200112L - -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace context { - -BOOST_CONTEXT_DECL std::size_t pagesize(); - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -//#endif - -#endif // BOOST_CONTEXT_UTILS_H diff --git a/performance/performance.cpp b/performance/performance.cpp index 1d4e6e4..998518c 100644 --- a/performance/performance.cpp +++ b/performance/performance.cpp @@ -19,6 +19,8 @@ #include #include +#include "../example/simple_stack_allocator.hpp" + #ifdef BOOST_USE_UCONTEXT #include #endif @@ -32,6 +34,12 @@ namespace ctx = boost::context; +typedef ctx::simple_stack_allocator< + 8 * 1024 * 1024, // 8MB + 64 * 1024, // 64kB + 8 * 1024 // 8kB +> stack_allocator; + bool pres_fpu = false; #define CALL_FCONTEXT(z,n,unused) ctx::jump_fcontext( & fcm, fc, 7, pres_fpu); @@ -65,10 +73,10 @@ static void f3() #ifdef BOOST_CONTEXT_CYCLE cycle_t test_fcontext_cycle( cycle_t ov) { - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; fc = ctx::make_fcontext( - alloc.allocate(ctx::guarded_stack_allocator::default_stacksize()), - ctx::guarded_stack_allocator::default_stacksize(), + alloc.allocate(stack_allocator::default_stacksize()), + stack_allocator::default_stacksize(), f1); ctx::jump_fcontext( & fcm, fc, 7, pres_fpu); @@ -91,11 +99,11 @@ BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~) # ifdef BOOST_USE_UCONTEXT cycle_t test_ucontext_cycle( cycle_t ov) { - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; ::getcontext( & uc); - uc.uc_stack.ss_sp = alloc.allocate(ctx::guarded_stack_allocator_stacksize()); - uc.uc_stack.ss_size = ctx::guarded_stack_allocator_stacksize(); + uc.uc_stack.ss_sp = alloc.allocate(stack_allocator::default_stacksize()); + uc.uc_stack.ss_size = stack_allocator::default_stacksize(); ::makecontext( & uc, f2, 7); // cache warum-up @@ -137,10 +145,10 @@ BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~) #if _POSIX_C_SOURCE >= 199309L zeit_t test_fcontext_zeit( zeit_t ov) { - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; fc = ctx::make_fcontext( - alloc.allocate(ctx::guarded_stack_allocator::default_stacksize()), - ctx::guarded_stack_allocator::default_stacksize(), + alloc.allocate(stack_allocator::default_stacksize()), + stack_allocator::default_stacksize(), f1); ctx::jump_fcontext( & fcm, fc, 7, pres_fpu); @@ -163,11 +171,11 @@ BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~) # ifdef BOOST_USE_UCONTEXT zeit_t test_ucontext_zeit( zeit_t ov) { - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; ::getcontext( & uc); - uc.uc_stack.ss_sp = alloc.allocate(ctx::guarded_stack_allocator_stacksize()); - uc.uc_stack.ss_size = ctx::guarded_stack_allocator_stacksize(); + uc.uc_stack.ss_sp = alloc.allocate(stack_allocator::default_stacksize()); + uc.uc_stack.ss_size = stack_allocator::default_stacksize(); ::makecontext( & uc, f2, 7); // cache warum-up diff --git a/src/guarded_stack_allocator_posix.cpp b/src/guarded_stack_allocator_posix.cpp deleted file mode 100644 index 8f68294..0000000 --- a/src/guarded_stack_allocator_posix.cpp +++ /dev/null @@ -1,152 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// 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 BOOST_CONTEXT_SOURCE - -#include - -extern "C" { -#include -#include -#include -#include -#include -#include -#include -#include -} - -//#if _POSIX_C_SOURCE >= 200112L - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#if !defined (SIGSTKSZ) -# define SIGSTKSZ (8 * 1024) -#endif - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace { - -static rlimit stacksize_limit_() -{ - rlimit limit; - // conforming to POSIX.1-2001 - const int result = ::getrlimit( RLIMIT_STACK, & limit); - BOOST_ASSERT( 0 == result); - return limit; -} - -static rlimit stacksize_limit() -{ - static rlimit limit = stacksize_limit_(); - return limit; -} - -static std::size_t page_count( std::size_t stacksize) -{ - return static_cast< std::size_t >( - std::ceil( - static_cast< float >( stacksize) / boost::context::pagesize() ) ); -} - -} - -namespace boost { -namespace context { - -bool -guarded_stack_allocator::is_stack_unbound() -{ return RLIM_INFINITY == stacksize_limit().rlim_max; } - -std::size_t -guarded_stack_allocator::maximum_stacksize() -{ - BOOST_ASSERT( ! is_stack_unbound() ); - return static_cast< std::size_t >( stacksize_limit().rlim_max); -} - -std::size_t -guarded_stack_allocator::minimum_stacksize() -{ return SIGSTKSZ + sizeof( fcontext_t) + 15; } - -std::size_t -guarded_stack_allocator::default_stacksize() -{ - std::size_t size = 8 * minimum_stacksize(); - if ( is_stack_unbound() ) return size; - - BOOST_ASSERT( maximum_stacksize() >= minimum_stacksize() ); - return maximum_stacksize() == size - ? size - : std::min( size, maximum_stacksize() ); -} - -void * -guarded_stack_allocator::allocate( std::size_t size) const -{ - BOOST_ASSERT( minimum_stacksize() <= size); - BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) ); - - const std::size_t pages( page_count( size) + 1); // add one guard page - const std::size_t size_( pages * pagesize() ); - BOOST_ASSERT( 0 < size && 0 < size_); - - const int fd( ::open("/dev/zero", O_RDONLY) ); - BOOST_ASSERT( -1 != fd); - // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L) - void * limit = -# if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) - ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); -# else - ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); -# endif - ::close( fd); - if ( ! limit) throw std::bad_alloc(); - - std::memset( limit, size_, '\0'); - - // conforming to POSIX.1-2001 - const int result( ::mprotect( limit, pagesize(), PROT_NONE) ); - BOOST_ASSERT( 0 == result); - - return static_cast< char * >( limit) + size_; -} - -void -guarded_stack_allocator::deallocate( void * vp, std::size_t size) const -{ - BOOST_ASSERT( vp); - BOOST_ASSERT( minimum_stacksize() <= size); - BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) ); - - const std::size_t pages = page_count( size) + 1; - const std::size_t size_ = pages * pagesize(); - BOOST_ASSERT( 0 < size && 0 < size_); - void * limit = static_cast< char * >( vp) - size_; - // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L) - ::munmap( limit, size_); -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -//#endif diff --git a/src/guarded_stack_allocator_windows.cpp b/src/guarded_stack_allocator_windows.cpp deleted file mode 100644 index c08af5f..0000000 --- a/src/guarded_stack_allocator_windows.cpp +++ /dev/null @@ -1,156 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// 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 BOOST_CONTEXT_SOURCE -#define NOMINMAX - -#include - -extern "C" { -#include -} - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -# if defined(BOOST_MSVC) -# pragma warning(push) -# pragma warning(disable:4244 4267) -# endif - -// x86_64 -// test x86_64 before i386 because icc might -// define __i686__ for x86_64 too -#if defined(__x86_64__) || defined(__x86_64) \ - || defined(__amd64__) || defined(__amd64) \ - || defined(_M_X64) || defined(_M_AMD64) - -// Windows seams not to provide a constant or function -// telling the minimal stacksize -# define MIN_STACKSIZE 8 * 1024 -#else -# define MIN_STACKSIZE 4 * 1024 -#endif - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace { - -static SYSTEM_INFO system_info_() -{ - SYSTEM_INFO si; - ::GetSystemInfo( & si); - return si; -} - -static SYSTEM_INFO system_info() -{ - static SYSTEM_INFO si = system_info_(); - return si; -} - -static std::size_t page_count( std::size_t stacksize) -{ - return static_cast< std::size_t >( - std::ceil( - static_cast< float >( stacksize) / boost::context::pagesize() ) ); -} - -} - -namespace boost { -namespace context { - -// Windows seams not to provide a limit for the stacksize -bool -guarded_stack_allocator::is_stack_unbound() -{ return true; } - -// because Windows seams not to provide a limit for maximum stacksize -// maximum_stacksize() can never be called (pre-condition ! is_stack_unbound() ) -std::size_t -guarded_stack_allocator::maximum_stacksize() -{ - BOOST_ASSERT( ! is_stack_unbound() ); - return 1 * 1024 * 1024 * 1024; // 1GB -} - -// because Windows seams not to provide a limit for minimum stacksize -std::size_t -guarded_stack_allocator::minimum_stacksize() -{ return MIN_STACKSIZE; } - -std::size_t -guarded_stack_allocator::default_stacksize() -{ - std::size_t size = 64 * 1024; // 64 kB - if ( is_stack_unbound() ) - return std::max( size, minimum_stacksize() ); - - BOOST_ASSERT( maximum_stacksize() >= minimum_stacksize() ); - return maximum_stacksize() == minimum_stacksize() - ? minimum_stacksize() - : std::min( size, maximum_stacksize() ); -} - -void * -guarded_stack_allocator::allocate( std::size_t size) const -{ - BOOST_ASSERT( minimum_stacksize() <= size); - BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) ); - - const std::size_t pages( page_count( size) + 1); // add one guard page - const std::size_t size_ = pages * pagesize(); - BOOST_ASSERT( 0 < size && 0 < size_); - - void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE); - if ( ! limit) throw std::bad_alloc(); - - std::memset( limit, size_, '\0'); - - DWORD old_options; - const BOOL result = ::VirtualProtect( - limit, pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options); - BOOST_ASSERT( FALSE != result); - - return static_cast< char * >( limit) + size_; -} - -void -guarded_stack_allocator::deallocate( void * vp, std::size_t size) const -{ - BOOST_ASSERT( vp); - BOOST_ASSERT( minimum_stacksize() <= size); - BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) ); - - const std::size_t pages = page_count( size) + 1; - const std::size_t size_ = pages * pagesize(); - BOOST_ASSERT( 0 < size && 0 < size_); - void * limit = static_cast< char * >( vp) - size_; - ::VirtualFree( limit, 0, MEM_RELEASE); -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -# if defined(BOOST_MSVC) -# pragma warning(pop) -# endif diff --git a/src/utils_posix.cpp b/src/utils_posix.cpp deleted file mode 100644 index 7d16b9b..0000000 --- a/src/utils_posix.cpp +++ /dev/null @@ -1,39 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// 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 BOOST_CONTEXT_SOURCE - -#include - -extern "C" { -#include -} - -//#if _POSIX_C_SOURCE >= 200112L - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace context { - -std::size_t pagesize() -{ - // conform to POSIX.1-2001 - static std::size_t size = ::sysconf( _SC_PAGESIZE); - return size; -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -//#endif diff --git a/src/utils_windows.cpp b/src/utils_windows.cpp deleted file mode 100644 index c50c105..0000000 --- a/src/utils_windows.cpp +++ /dev/null @@ -1,48 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// 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 BOOST_CONTEXT_SOURCE - -#include - -extern "C" { -#include -} - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace { - -static SYSTEM_INFO system_info_() -{ - SYSTEM_INFO si; - ::GetSystemInfo( & si); - return si; -} - -static SYSTEM_INFO system_info() -{ - static SYSTEM_INFO si = system_info_(); - return si; -} - -} - -namespace boost { -namespace context { - -std::size_t pagesize() -{ return static_cast< std::size_t >( system_info().dwPageSize); } - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/test/test_context.cpp b/test/test_context.cpp index b85d1cb..b09360f 100644 --- a/test/test_context.cpp +++ b/test/test_context.cpp @@ -17,8 +17,16 @@ #include +#include "../example/simple_stack_allocator.hpp" + namespace ctx = boost::context; +typedef ctx::simple_stack_allocator< + 8 * 1024 * 1024, // 8MB + 64 * 1024, // 64kB + 8 * 1024 // 8kB +> stack_allocator; + ctx::fcontext_t fcm; ctx::fcontext_t * fc = 0; int value1 = 0; @@ -76,43 +84,28 @@ void f8( intptr_t arg) ctx::jump_fcontext( fc, & fcm, 0); } -void test_stack() -{ - ctx::guarded_stack_allocator alloc; - - bool unbound = ctx::guarded_stack_allocator::is_stack_unbound(); - std::size_t min = ctx::guarded_stack_allocator::minimum_stacksize(); - std::size_t def = ctx::guarded_stack_allocator::default_stacksize(); - BOOST_CHECK( min <= def); - if ( ! unbound) - { - std::size_t max = ctx::guarded_stack_allocator::maximum_stacksize(); - BOOST_CHECK( max >= def); - } -} - void test_setup() { - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; - void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() ); - fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f1); + void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); + fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f1); BOOST_CHECK( fc); BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp); - BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size); + BOOST_CHECK_EQUAL( stack_allocator::minimum_stacksize(), fc->fc_stack.size); } void test_start() { value1 = 0; - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; - void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() ); - fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f1); + void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); + fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f1); BOOST_CHECK( fc); BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp); - BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size); + BOOST_CHECK_EQUAL( stack_allocator::minimum_stacksize(), fc->fc_stack.size); BOOST_CHECK_EQUAL( 0, value1); ctx::jump_fcontext( & fcm, fc, 0); @@ -123,13 +116,13 @@ void test_jump() { value1 = 0; - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; - void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() ); - fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f3); + void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); + fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f3); BOOST_CHECK( fc); BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp); - BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size); + BOOST_CHECK_EQUAL( stack_allocator::minimum_stacksize(), fc->fc_stack.size); BOOST_CHECK_EQUAL( 0, value1); ctx::jump_fcontext( & fcm, fc, 0); @@ -140,13 +133,13 @@ void test_jump() void test_result() { - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; - void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() ); - fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f4); + void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); + fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f4); BOOST_CHECK( fc); BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp); - BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size); + BOOST_CHECK_EQUAL( stack_allocator::minimum_stacksize(), fc->fc_stack.size); int result = ( int) ctx::jump_fcontext( & fcm, fc, 0); BOOST_CHECK_EQUAL( 7, result); @@ -154,14 +147,14 @@ void test_result() void test_arg() { - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; int i = 7; - void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() ); - fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f5); + void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); + fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f5); BOOST_CHECK( fc); BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp); - BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size); + BOOST_CHECK_EQUAL( stack_allocator::minimum_stacksize(), fc->fc_stack.size); int result = ( int) ctx::jump_fcontext( & fcm, fc, i); BOOST_CHECK_EQUAL( i, result); @@ -169,14 +162,14 @@ void test_arg() void test_transfer() { - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; std::pair< int, int > data = std::make_pair( 3, 7); - void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() ); - fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f6); + void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); + fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f6); BOOST_CHECK( fc); BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp); - BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size); + BOOST_CHECK_EQUAL( stack_allocator::minimum_stacksize(), fc->fc_stack.size); int result = ( int) ctx::jump_fcontext( & fcm, fc, ( intptr_t) & data); BOOST_CHECK_EQUAL( 10, result); @@ -187,14 +180,14 @@ void test_transfer() void test_exception() { - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; const char * what = "hello world"; - void * sp = alloc.allocate( ctx::guarded_stack_allocator::default_stacksize() ); - fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::default_stacksize(), f7); + void * sp = alloc.allocate( stack_allocator::default_stacksize() ); + fc = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f7); BOOST_CHECK( fc); BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp); - BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::default_stacksize(), fc->fc_stack.size); + BOOST_CHECK_EQUAL( stack_allocator::default_stacksize(), fc->fc_stack.size); ctx::jump_fcontext( & fcm, fc, ( intptr_t) what); BOOST_CHECK_EQUAL( std::string( what), value2); @@ -202,14 +195,14 @@ void test_exception() void test_fp() { - ctx::guarded_stack_allocator alloc; + stack_allocator alloc; double d = 7.13; - void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() ); - fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f8); + void * sp = alloc.allocate( stack_allocator::minimum_stacksize() ); + fc = ctx::make_fcontext( sp, stack_allocator::minimum_stacksize(), f8); BOOST_CHECK( fc); BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp); - BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size); + BOOST_CHECK_EQUAL( stack_allocator::minimum_stacksize(), fc->fc_stack.size); ctx::jump_fcontext( & fcm, fc, (intptr_t) & d); BOOST_CHECK_EQUAL( 10.58, value3); @@ -220,7 +213,6 @@ boost::unit_test::test_suite * init_unit_test_suite( int, char* []) boost::unit_test::test_suite * test = BOOST_TEST_SUITE("Boost.Context: context test suite"); - test->add( BOOST_TEST_CASE( & test_stack) ); test->add( BOOST_TEST_CASE( & test_setup) ); test->add( BOOST_TEST_CASE( & test_start) ); test->add( BOOST_TEST_CASE( & test_jump) );