protected_fixedsize_stack.hpp 3.0 KB

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