libcopp  1.1.0
stack_allocator_posix.cpp
Go to the documentation of this file.
1 extern "C" {
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <signal.h>
5 #include <sys/mman.h>
6 #include <sys/resource.h>
7 #include <sys/stat.h>
8 #include <sys/time.h>
9 #include <sys/types.h>
10 #include <unistd.h>
11 }
12 
13 #include <algorithm>
14 #include <assert.h>
15 #include <cstring>
16 #include <iostream>
17 #include <limits>
18 #include <numeric>
19 
20 
25 
26 #if defined(LIBCOPP_MACRO_USE_VALGRIND)
27 #include <valgrind/valgrind.h>
28 #endif
29 
30 #ifdef COPP_HAS_ABI_HEADERS
31 #include COPP_ABI_PREFIX
32 #endif
33 
34 namespace copp {
35  namespace allocator {
37 
39 
40  void stack_allocator_posix::allocate(stack_context &ctx, std::size_t size) UTIL_CONFIG_NOEXCEPT {
41  size = (std::max)(size, stack_traits::minimum_size());
42  size = (std::min)(size, stack_traits::maximum_size());
43 
44  std::size_t size_ = stack_traits::round_to_page_size(size) + stack_traits::page_size(); // add one protected page
45  assert(size > 0 && size_ > 0);
46 
47  // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
48  void *start_ptr =
49 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
50  ::mmap(0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
51 #else
52  ::mmap(0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
53 #endif
54 
55  if (!start_ptr || MAP_FAILED == start_ptr) {
56  ctx.sp = NULL;
57  return;
58  }
59 
60  // memset(start_ptr, 0, size_);
61  ::mprotect(start_ptr, stack_traits::page_size(), PROT_NONE);
62 
63  ctx.size = size_;
64  ctx.sp = static_cast<char *>(start_ptr) + ctx.size; // stack down
65 
66 #if defined(LIBCOPP_MACRO_USE_VALGRIND)
67  ctx.valgrind_stack_id = VALGRIND_STACK_REGISTER(ctx.sp, start_ptr);
68 #endif
69  }
70 
71  void stack_allocator_posix::deallocate(stack_context &ctx) UTIL_CONFIG_NOEXCEPT {
72  assert(ctx.sp);
73  assert(stack_traits::minimum_size() <= ctx.size);
74  assert(stack_traits::is_unbounded() || (stack_traits::maximum_size() >= ctx.size));
75 
76 #if defined(LIBCOPP_MACRO_USE_VALGRIND)
77  VALGRIND_STACK_DEREGISTER(ctx.valgrind_stack_id);
78 #endif
79 
80  void *start_ptr = static_cast<char *>(ctx.sp) - ctx.size;
81  ::munmap(start_ptr, ctx.size);
82  }
83  }
84 }
85 
86 #ifdef COPP_HAS_ABI_HEADERS
87 #include COPP_ABI_SUFFIX
88 #endif
static std::size_t page_size() COPP_MACRO_NOEXCEPT
void deallocate(stack_context &) UTIL_CONFIG_NOEXCEPT
void allocate(stack_context &, std::size_t) UTIL_CONFIG_NOEXCEPT
static bool is_unbounded() COPP_MACRO_NOEXCEPT
static std::size_t maximum_size() COPP_MACRO_NOEXCEPT
static std::size_t minimum_size() COPP_MACRO_NOEXCEPT
static std::size_t round_to_page_size(std::size_t stacksize) COPP_MACRO_NOEXCEPT