libcopp 2.3.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
14extern "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 LIBCOPP_HAS_ABI_HEADERS
40# include LIBCOPP_ABI_PREFIX
41#endif
42
43LIBCOPP_COPP_NAMESPACE_BEGIN
44namespace allocator {
45LIBCOPP_COPP_API stack_allocator_posix::stack_allocator_posix() LIBCOPP_MACRO_NOEXCEPT {}
47LIBCOPP_COPP_API stack_allocator_posix::stack_allocator_posix(const stack_allocator_posix &) LIBCOPP_MACRO_NOEXCEPT {}
49 LIBCOPP_MACRO_NOEXCEPT {
50 return *this;
51}
52
53LIBCOPP_COPP_API stack_allocator_posix::stack_allocator_posix(stack_allocator_posix &&) LIBCOPP_MACRO_NOEXCEPT {}
55 LIBCOPP_MACRO_NOEXCEPT {
56 return *this;
57}
58
59LIBCOPP_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
90LIBCOPP_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
103LIBCOPP_COPP_NAMESPACE_END
104
105#ifdef LIBCOPP_HAS_ABI_HEADERS
106# include LIBCOPP_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
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