1 2 // Copyright Oliver Kowalke 2009. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 #ifndef BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H 8 #define BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H 9 10 extern "C" { 11 #include <windows.h> 12 } 13 14 #include <cmath> 15 #include <cstddef> 16 #include <new> 17 18 #include <boost/config.hpp> 19 20 #include <boost/coroutine/detail/config.hpp> 21 #include <boost/coroutine/stack_traits.hpp> 22 23 #ifdef BOOST_HAS_ABI_HEADERS 24 # include BOOST_ABI_PREFIX 25 #endif 26 27 namespace boost { 28 namespace coroutines { 29 30 struct stack_context; 31 32 template< typename traitsT > 33 struct basic_protected_stack_allocator 34 { 35 typedef traitsT traits_type; 36 allocateboost::coroutines::basic_protected_stack_allocator37 void allocate( stack_context & ctx, std::size_t size) 38 { 39 BOOST_ASSERT( traits_type::minimum_size() <= size); 40 BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size) ); 41 42 // page at bottom will be used as guard-page 43 const std::size_t pages( 44 static_cast< std::size_t >( 45 std::floor( 46 static_cast< float >( size) / traits_type::page_size() ) ) ); 47 BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)"); 48 const std::size_t size_ = pages * traits_type::page_size(); 49 BOOST_ASSERT( 0 != size && 0 != size_); 50 51 void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE); 52 if ( ! limit) throw std::bad_alloc(); 53 54 DWORD old_options; 55 #if defined(BOOST_DISABLE_ASSERTS) 56 ::VirtualProtect( 57 limit, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options); 58 #else 59 const BOOL result = ::VirtualProtect( 60 limit, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options); 61 BOOST_ASSERT( FALSE != result); 62 #endif 63 64 ctx.size = size_; 65 ctx.sp = static_cast< char * >( limit) + ctx.size; 66 } 67 deallocateboost::coroutines::basic_protected_stack_allocator68 void deallocate( stack_context & ctx) 69 { 70 BOOST_ASSERT( ctx.sp); 71 BOOST_ASSERT( traits_type::minimum_size() <= ctx.size); 72 BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= ctx.size) ); 73 74 void * limit = static_cast< char * >( ctx.sp) - ctx.size; 75 ::VirtualFree( limit, 0, MEM_RELEASE); 76 } 77 }; 78 79 typedef basic_protected_stack_allocator< stack_traits > protected_stack_allocator; 80 81 }} 82 83 #ifdef BOOST_HAS_ABI_HEADERS 84 # include BOOST_ABI_SUFFIX 85 #endif 86 87 #endif // BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H 88