libcopp  2.2.0
stack_allocator_posix.cpp
Go to the documentation of this file.
1 // Copyright 2023 owent
2 
3 #include <libcopp/utils/config/libcopp_build_features.h>
4 
9 
10 #if defined(LIBCOPP_MACRO_USE_VALGRIND)
11 # include <valgrind/valgrind.h>
12 #endif
13 
14 extern "C" {
15 #include <errno.h>
16 #include <fcntl.h>
17 #include <signal.h>
18 #include <sys/mman.h>
19 #include <sys/resource.h>
20 #include <sys/stat.h>
21 #include <sys/time.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 }
25 
26 // clang-format off
27 #include <libcopp/utils/config/stl_include_prefix.h> // NOLINT(build/include_order)
28 // clang-format on
29 #include <assert.h>
30 #include <algorithm>
31 #include <cstring>
32 #include <iostream>
33 #include <limits>
34 #include <numeric>
35 // clang-format off
36 #include <libcopp/utils/config/stl_include_suffix.h> // NOLINT(build/include_order)
37 // clang-format on
38 
39 #ifdef COPP_HAS_ABI_HEADERS
40 # include COPP_ABI_PREFIX
41 #endif
42 
43 LIBCOPP_COPP_NAMESPACE_BEGIN
44 namespace allocator {
45 LIBCOPP_COPP_API stack_allocator_posix::stack_allocator_posix() LIBCOPP_MACRO_NOEXCEPT {}
47 LIBCOPP_COPP_API stack_allocator_posix::stack_allocator_posix(const stack_allocator_posix &) LIBCOPP_MACRO_NOEXCEPT {}
49  LIBCOPP_MACRO_NOEXCEPT {
50  return *this;
51 }
52 
53 LIBCOPP_COPP_API stack_allocator_posix::stack_allocator_posix(stack_allocator_posix &&) LIBCOPP_MACRO_NOEXCEPT {}
55  LIBCOPP_MACRO_NOEXCEPT {
56  return *this;
57 }
58 
59 LIBCOPP_COPP_API void stack_allocator_posix::allocate(stack_context &ctx, std::size_t size) LIBCOPP_MACRO_NOEXCEPT {
60  size = (std::max)(size, stack_traits::minimum_size());
61  size = (std::min)(size, stack_traits::maximum_size());
62 
63  std::size_t size_ = stack_traits::round_to_page_size(size) + stack_traits::page_size(); // add one protected page
64  assert(size > 0 && size_ > 0);
65 
66  // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
67  void *start_ptr =
68 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
69  ::mmap(0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
70 #else
71  ::mmap(0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
72 #endif
73 
74  if (!start_ptr || MAP_FAILED == start_ptr) {
75  ctx.sp = nullptr;
76  return;
77  }
78 
79  // memset(start_ptr, 0, size_);
80  ::mprotect(start_ptr, stack_traits::page_size(), PROT_NONE);
81 
82  ctx.size = size_;
83  ctx.sp = static_cast<char *>(start_ptr) + ctx.size; // stack down
84 
85 #if defined(LIBCOPP_MACRO_USE_VALGRIND)
86  ctx.valgrind_stack_id = VALGRIND_STACK_REGISTER(ctx.sp, start_ptr);
87 #endif
88 }
89 
90 LIBCOPP_COPP_API void stack_allocator_posix::deallocate(stack_context &ctx) LIBCOPP_MACRO_NOEXCEPT {
91  assert(ctx.sp);
92  assert(stack_traits::minimum_size() <= ctx.size);
93  assert(stack_traits::is_unbounded() || (stack_traits::maximum_size() >= ctx.size));
94 
95 #if defined(LIBCOPP_MACRO_USE_VALGRIND)
96  VALGRIND_STACK_DEREGISTER(ctx.valgrind_stack_id);
97 #endif
98 
99  void *start_ptr = static_cast<char *>(ctx.sp) - ctx.size;
100  ::munmap(start_ptr, ctx.size);
101 }
102 } // namespace allocator
103 LIBCOPP_COPP_NAMESPACE_END
104 
105 #ifdef COPP_HAS_ABI_HEADERS
106 # include COPP_ABI_SUFFIX
107 #endif
memory allocator this allocator will create buffer using posix api and protect it
void allocate(stack_context &, std::size_t) LIBCOPP_MACRO_NOEXCEPT
void deallocate(stack_context &) LIBCOPP_MACRO_NOEXCEPT
stack_allocator_posix & operator=(const stack_allocator_posix &other) LIBCOPP_MACRO_NOEXCEPT
stack_allocator_posix() LIBCOPP_MACRO_NOEXCEPT
constexpr auto size(TCONTAINER &&container) -> decltype(container.size())
Definition: span.h:44
static LIBCOPP_COPP_API std::size_t page_size() LIBCOPP_MACRO_NOEXCEPT
static LIBCOPP_COPP_API std::size_t maximum_size() LIBCOPP_MACRO_NOEXCEPT
static LIBCOPP_COPP_API std::size_t round_to_page_size(std::size_t stacksize) LIBCOPP_MACRO_NOEXCEPT
static LIBCOPP_COPP_API std::size_t minimum_size() LIBCOPP_MACRO_NOEXCEPT
static LIBCOPP_COPP_API bool is_unbounded() LIBCOPP_MACRO_NOEXCEPT