Imported Upstream version 1.51.0
[platform/upstream/boost.git] / libs / context / src / stack_allocator_posix.cpp
1
2 //          Copyright Oliver Kowalke 2009.
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 #define BOOST_CONTEXT_SOURCE
8
9 #include <boost/context/stack_allocator.hpp>
10
11 extern "C" {
12 #include <fcntl.h>
13 #include <sys/mman.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17 }
18
19 #include <stdexcept>
20
21 #include <boost/config.hpp>
22 #include <boost/assert.hpp>
23 #include <boost/format.hpp>
24
25 #include <boost/context/stack_utils.hpp>
26
27 #ifdef BOOST_HAS_ABI_HEADERS
28 #  include BOOST_ABI_PREFIX
29 #endif
30
31 namespace boost {
32 namespace ctx {
33
34 void *
35 stack_allocator::allocate( std::size_t size) const
36 {
37     if ( minimum_stacksize() > size)
38         throw std::invalid_argument(
39             boost::str( boost::format("invalid stack size: must be at least %d bytes")
40                 % minimum_stacksize() ) );
41
42     if ( ! is_stack_unbound() && ( maximum_stacksize() < size) )
43         throw std::invalid_argument(
44             boost::str( boost::format("invalid stack size: must not be larger than %d bytes")
45                 % maximum_stacksize() ) );
46
47     const std::size_t pages( page_count( size) + 1); // add +1 for guard page
48     std::size_t size_ = pages * pagesize();
49
50     const int fd( ::open("/dev/zero", O_RDONLY) );
51     BOOST_ASSERT( -1 != fd);
52     void * limit =
53 # if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
54         ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
55 # else
56         ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
57 # endif
58     ::close( fd);
59     if ( ! limit) throw std::bad_alloc();
60
61     const int result( ::mprotect( limit, pagesize(), PROT_NONE) );
62     BOOST_ASSERT( 0 == result);
63
64     return static_cast< char * >( limit) + size_;
65 }
66
67 void
68 stack_allocator::deallocate( void * vp, std::size_t size) const
69 {
70     if ( vp)
71     {
72         const std::size_t pages( page_count( size) + 1); // add +1 for guard page
73         std::size_t size_ = pages * pagesize();
74         BOOST_ASSERT( 0 < size && 0 < size_);
75         void * limit = static_cast< char * >( vp) - size_;
76         ::munmap( limit, size_);
77     }
78 }
79
80 }}
81
82 #ifdef BOOST_HAS_ABI_HEADERS
83 #  include BOOST_ABI_SUFFIX
84 #endif