protected_fixedsize_stack.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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/core/ignore_unused.hpp>
  19. #include <boost/context/detail/config.hpp>
  20. #include <boost/context/stack_context.hpp>
  21. #include <boost/context/stack_traits.hpp>
  22. #if defined(BOOST_USE_VALGRIND)
  23. #include <valgrind/valgrind.h>
  24. #endif
  25. #ifdef BOOST_HAS_ABI_HEADERS
  26. # include BOOST_ABI_PREFIX
  27. #endif
  28. namespace boost {
  29. namespace context {
  30. template< typename traitsT >
  31. class basic_protected_fixedsize_stack {
  32. private:
  33. std::size_t size_;
  34. public:
  35. typedef traitsT traits_type;
  36. basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW :
  37. size_( size) {
  38. }
  39. stack_context allocate() {
  40. // calculate how many pages are required
  41. const std::size_t pages = (size_ + traits_type::page_size() - 1) / traits_type::page_size();
  42. // add one page at bottom that will be used as guard-page
  43. const std::size_t size__ = ( pages + 1) * traits_type::page_size();
  44. #if defined(BOOST_CONTEXT_USE_MAP_STACK)
  45. void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
  46. #elif defined(MAP_ANON)
  47. void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
  48. #else
  49. void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  50. #endif
  51. if ( MAP_FAILED == vp) throw std::bad_alloc();
  52. // conforming to POSIX.1-2001
  53. const int result( ::mprotect( vp, traits_type::page_size(), PROT_NONE) );
  54. boost::ignore_unused(result);
  55. BOOST_ASSERT( 0 == result);
  56. stack_context sctx;
  57. sctx.size = size__;
  58. sctx.sp = static_cast< char * >( vp) + sctx.size;
  59. #if defined(BOOST_USE_VALGRIND)
  60. sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp);
  61. #endif
  62. return sctx;
  63. }
  64. void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
  65. BOOST_ASSERT( sctx.sp);
  66. #if defined(BOOST_USE_VALGRIND)
  67. VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
  68. #endif
  69. void * vp = static_cast< char * >( sctx.sp) - sctx.size;
  70. // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
  71. ::munmap( vp, sctx.size);
  72. }
  73. };
  74. typedef basic_protected_fixedsize_stack< stack_traits > protected_fixedsize_stack;
  75. }}
  76. #ifdef BOOST_HAS_ABI_HEADERS
  77. # include BOOST_ABI_SUFFIX
  78. #endif
  79. #endif // BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H