1 2 // Copyright Oliver Kowalke 2014. 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_CONTEXT_PROTECTED_FIXEDSIZE_H 8 #define BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H 9 10 extern "C" { 11 #include <fcntl.h> 12 #include <sys/mman.h> 13 #include <sys/stat.h> 14 #include <unistd.h> 15 } 16 17 #include <cmath> 18 #include <cstddef> 19 #include <new> 20 21 #include <boost/assert.hpp> 22 #include <boost/config.hpp> 23 #include <boost/core/ignore_unused.hpp> 24 25 #include <boost/context/detail/config.hpp> 26 #include <boost/context/stack_context.hpp> 27 #include <boost/context/stack_traits.hpp> 28 29 #if defined(BOOST_USE_VALGRIND) 30 #include <valgrind/valgrind.h> 31 #endif 32 33 #ifdef BOOST_HAS_ABI_HEADERS 34 # include BOOST_ABI_PREFIX 35 #endif 36 37 namespace boost { 38 namespace context { 39 40 template< typename traitsT > 41 class basic_protected_fixedsize_stack { 42 private: 43 std::size_t size_; 44 45 public: 46 typedef traitsT traits_type; 47 basic_protected_fixedsize_stack(std::size_t size=traits_type::default_size ())48 basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW : 49 size_( size) { 50 } 51 allocate()52 stack_context allocate() { 53 // calculate how many pages are required 54 const std::size_t pages( 55 static_cast< std::size_t >( 56 std::ceil( 57 static_cast< float >( size_) / traits_type::page_size() ) ) ); 58 // add one page at bottom that will be used as guard-page 59 const std::size_t size__ = ( pages + 1) * traits_type::page_size(); 60 61 #if defined(BOOST_CONTEXT_USE_MAP_STACK) 62 void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0); 63 #elif defined(MAP_ANON) 64 void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); 65 #else 66 void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 67 #endif 68 if ( MAP_FAILED == vp) throw std::bad_alloc(); 69 70 // conforming to POSIX.1-2001 71 const int result( ::mprotect( vp, traits_type::page_size(), PROT_NONE) ); 72 boost::ignore_unused(result); 73 BOOST_ASSERT( 0 == result); 74 75 stack_context sctx; 76 sctx.size = size__; 77 sctx.sp = static_cast< char * >( vp) + sctx.size; 78 #if defined(BOOST_USE_VALGRIND) 79 sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp); 80 #endif 81 return sctx; 82 } 83 deallocate(stack_context & sctx)84 void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW { 85 BOOST_ASSERT( sctx.sp); 86 87 #if defined(BOOST_USE_VALGRIND) 88 VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id); 89 #endif 90 91 void * vp = static_cast< char * >( sctx.sp) - sctx.size; 92 // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L) 93 ::munmap( vp, sctx.size); 94 } 95 }; 96 97 typedef basic_protected_fixedsize_stack< stack_traits > protected_fixedsize_stack; 98 99 }} 100 101 #ifdef BOOST_HAS_ABI_HEADERS 102 # include BOOST_ABI_SUFFIX 103 #endif 104 105 #endif // BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H 106