protected_stack_allocator.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright Oliver Kowalke 2009.
  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_COROUTINES_PROTECTED_STACK_ALLOCATOR_H
  6. #define BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H
  7. extern "C" {
  8. #include <windows.h>
  9. }
  10. #include <cmath>
  11. #include <cstddef>
  12. #include <new>
  13. #include <boost/config.hpp>
  14. #include <boost/coroutine/detail/config.hpp>
  15. #include <boost/coroutine/stack_traits.hpp>
  16. #ifdef BOOST_HAS_ABI_HEADERS
  17. # include BOOST_ABI_PREFIX
  18. #endif
  19. namespace boost {
  20. namespace coroutines {
  21. struct stack_context;
  22. template< typename traitsT >
  23. struct basic_protected_stack_allocator
  24. {
  25. typedef traitsT traits_type;
  26. void allocate( stack_context & ctx, std::size_t size)
  27. {
  28. BOOST_ASSERT( traits_type::minimum_size() <= size);
  29. BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size) );
  30. // page at bottom will be used as guard-page
  31. const std::size_t pages(
  32. static_cast< std::size_t >(
  33. std::floor(
  34. static_cast< float >( size) / traits_type::page_size() ) ) );
  35. BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
  36. const std::size_t size_ = pages * traits_type::page_size();
  37. BOOST_ASSERT( 0 != size && 0 != size_);
  38. void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE);
  39. if ( ! limit) throw std::bad_alloc();
  40. DWORD old_options;
  41. #if defined(BOOST_DISABLE_ASSERTS)
  42. ::VirtualProtect(
  43. limit, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
  44. #else
  45. const BOOL result = ::VirtualProtect(
  46. limit, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
  47. BOOST_ASSERT( FALSE != result);
  48. #endif
  49. ctx.size = size_;
  50. ctx.sp = static_cast< char * >( limit) + ctx.size;
  51. }
  52. void deallocate( stack_context & ctx)
  53. {
  54. BOOST_ASSERT( ctx.sp);
  55. BOOST_ASSERT( traits_type::minimum_size() <= ctx.size);
  56. BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= ctx.size) );
  57. void * limit = static_cast< char * >( ctx.sp) - ctx.size;
  58. ::VirtualFree( limit, 0, MEM_RELEASE);
  59. }
  60. };
  61. typedef basic_protected_stack_allocator< stack_traits > protected_stack_allocator;
  62. }}
  63. #ifdef BOOST_HAS_ABI_HEADERS
  64. # include BOOST_ABI_SUFFIX
  65. #endif
  66. #endif // BOOST_COROUTINES_PROTECTED_STACK_ALLOCATOR_H