summaryrefslogtreecommitdiff
path: root/boost/context/posix/protected_fixedsize_stack.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/context/posix/protected_fixedsize_stack.hpp')
-rw-r--r--boost/context/posix/protected_fixedsize_stack.hpp112
1 files changed, 112 insertions, 0 deletions
diff --git a/boost/context/posix/protected_fixedsize_stack.hpp b/boost/context/posix/protected_fixedsize_stack.hpp
new file mode 100644
index 0000000000..c7e09439fc
--- /dev/null
+++ b/boost/context/posix/protected_fixedsize_stack.hpp
@@ -0,0 +1,112 @@
+
+// Copyright Oliver Kowalke 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H
+#define BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H
+
+extern "C" {
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+}
+
+#include <cmath>
+#include <cstddef>
+#include <new>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+#include <boost/context/stack_context.hpp>
+#include <boost/context/stack_traits.hpp>
+
+#if defined(BOOST_USE_VALGRIND)
+#include <valgrind/valgrind.h>
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace context {
+
+template< typename traitsT >
+class basic_protected_fixedsize_stack {
+private:
+ std::size_t size_;
+
+public:
+ typedef traitsT traits_type;
+
+ basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) :
+ size_( size) {
+ BOOST_ASSERT( traits_type::minimum_size() <= size_);
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= size_) );
+ }
+
+ stack_context allocate() {
+ // page at bottom will be used as guard-page
+ const std::size_t pages(
+ static_cast< std::size_t >(
+ std::floor(
+ static_cast< float >( size_) / traits_type::page_size() ) ) );
+ BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
+ const std::size_t size__( pages * traits_type::page_size() );
+ BOOST_ASSERT( 0 < size_ && 0 < size__);
+ BOOST_ASSERT( size__ <= size_);
+
+ // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
+#if defined(MAP_ANON)
+ void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+#else
+ void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+#endif
+ if ( MAP_FAILED == vp) throw std::bad_alloc();
+
+ // conforming to POSIX.1-2001
+#if defined(BOOST_DISABLE_ASSERTS)
+ ::mprotect( vp, traits_type::page_size(), PROT_NONE);
+#else
+ const int result( ::mprotect( vp, traits_type::page_size(), PROT_NONE) );
+ BOOST_ASSERT( 0 == result);
+#endif
+
+ stack_context sctx;
+ sctx.size = size__;
+ sctx.sp = static_cast< char * >( vp) + sctx.size;
+#if defined(BOOST_USE_VALGRIND)
+ sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp);
+#endif
+ return sctx;
+ }
+
+ void deallocate( stack_context & sctx) {
+ BOOST_ASSERT( sctx.sp);
+ BOOST_ASSERT( traits_type::minimum_size() <= sctx.size);
+ BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
+
+#if defined(BOOST_USE_VALGRIND)
+ VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
+#endif
+
+ void * vp = static_cast< char * >( sctx.sp) - sctx.size;
+ // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
+ ::munmap( vp, sctx.size);
+ }
+};
+
+typedef basic_protected_fixedsize_stack< stack_traits > protected_fixedsize_stack;
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H