/src/WasmEdge/lib/system/allocator.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: 2019-2024 Second State INC |
3 | | |
4 | | #include "system/allocator.h" |
5 | | |
6 | | #include "common/config.h" |
7 | | #include "common/defines.h" |
8 | | #include "common/errcode.h" |
9 | | |
10 | | #if WASMEDGE_OS_WINDOWS |
11 | | #include "system/winapi.h" |
12 | | #elif defined(HAVE_MMAP) && defined(__x86_64__) || defined(__aarch64__) || \ |
13 | | defined(__arm__) || (defined(__riscv) && __riscv_xlen == 64) |
14 | | #include <sys/mman.h> |
15 | | #else |
16 | | #include <cctype> |
17 | | #include <cstdlib> |
18 | | #include <cstring> |
19 | | #endif |
20 | | |
21 | | namespace WasmEdge { |
22 | | |
23 | | namespace { |
24 | | static inline constexpr const uint64_t kPageSize = UINT64_C(65536); |
25 | | |
26 | | #if WASMEDGE_OS_WINDOWS || defined(HAVE_MMAP) && defined(__x86_64__) || \ |
27 | | defined(__aarch64__) || (defined(__riscv) && __riscv_xlen == 64) |
28 | | // Only define these two constants on the supported platform to avoid |
29 | | // -Wunused-const-variable error when applying -Werror. |
30 | | static inline constexpr const uint64_t k4G = UINT64_C(0x100000000); |
31 | | static inline constexpr const uint64_t k12G = UINT64_C(0x300000000); |
32 | | #endif |
33 | | |
34 | | } // namespace |
35 | | |
36 | 0 | WASMEDGE_EXPORT uint8_t *Allocator::allocate(uint32_t PageCount) noexcept { |
37 | | #if WASMEDGE_OS_WINDOWS |
38 | | auto Reserved = reinterpret_cast<uint8_t *>(winapi::VirtualAlloc( |
39 | | nullptr, k12G, winapi::MEM_RESERVE_, winapi::PAGE_NOACCESS_)); |
40 | | if (Reserved == nullptr) { |
41 | | return nullptr; |
42 | | } |
43 | | if (PageCount == 0) { |
44 | | return Reserved + k4G; |
45 | | } |
46 | | auto Pointer = resize(Reserved + k4G, 0, PageCount); |
47 | | if (Pointer == nullptr) { |
48 | | return nullptr; |
49 | | } |
50 | | return Pointer; |
51 | | #elif defined(HAVE_MMAP) && defined(__x86_64__) || defined(__aarch64__) || \ |
52 | | (defined(__riscv) && __riscv_xlen == 64) |
53 | | auto Reserved = reinterpret_cast<uint8_t *>( |
54 | 0 | mmap(nullptr, k12G, PROT_NONE, |
55 | 0 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0)); |
56 | 0 | if (Reserved == MAP_FAILED) { |
57 | 0 | return nullptr; |
58 | 0 | } |
59 | 0 | if (PageCount == 0) { |
60 | 0 | return Reserved + k4G; |
61 | 0 | } |
62 | 0 | auto Pointer = resize(Reserved + k4G, 0, PageCount); |
63 | 0 | if (Pointer == nullptr) { |
64 | 0 | return nullptr; |
65 | 0 | } |
66 | 0 | return Pointer; |
67 | | #else |
68 | | auto Result = reinterpret_cast<uint8_t *>(std::malloc(kPageSize * PageCount)); |
69 | | if (Result == nullptr) { |
70 | | return nullptr; |
71 | | } |
72 | | std::memset(Result, 0, kPageSize * PageCount); |
73 | | return Result; |
74 | | #endif |
75 | 0 | } |
76 | | |
77 | | WASMEDGE_EXPORT uint8_t *Allocator::resize(uint8_t *Pointer, |
78 | | uint32_t OldPageCount, |
79 | 0 | uint32_t NewPageCount) noexcept { |
80 | 0 | assuming(NewPageCount > OldPageCount); |
81 | | #if WASMEDGE_OS_WINDOWS |
82 | | if (winapi::VirtualAlloc(Pointer + OldPageCount * kPageSize, |
83 | | (NewPageCount - OldPageCount) * kPageSize, |
84 | | winapi::MEM_COMMIT_, |
85 | | winapi::PAGE_READWRITE_) == nullptr) { |
86 | | return nullptr; |
87 | | } |
88 | | return Pointer; |
89 | | #elif defined(HAVE_MMAP) && (defined(__x86_64__) || defined(__aarch64__) || \ |
90 | | (defined(__riscv) && __riscv_xlen == 64)) |
91 | 0 | if (mmap(Pointer + OldPageCount * kPageSize, |
92 | 0 | (NewPageCount - OldPageCount) * kPageSize, PROT_READ | PROT_WRITE, |
93 | 0 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0) == MAP_FAILED) { |
94 | 0 | return nullptr; |
95 | 0 | } |
96 | 0 | return Pointer; |
97 | | #else |
98 | | auto Result = reinterpret_cast<uint8_t *>( |
99 | | std::realloc(Pointer, NewPageCount * kPageSize)); |
100 | | if (Result == nullptr) { |
101 | | return nullptr; |
102 | | } |
103 | | std::memset(Result + OldPageCount * kPageSize, 0, |
104 | | (NewPageCount - OldPageCount) * kPageSize); |
105 | | return Result; |
106 | | #endif |
107 | 0 | } |
108 | | |
109 | 0 | WASMEDGE_EXPORT void Allocator::release(uint8_t *Pointer, uint32_t) noexcept { |
110 | | #if WASMEDGE_OS_WINDOWS |
111 | | winapi::VirtualFree(Pointer - k4G, 0, winapi::MEM_RELEASE_); |
112 | | #elif defined(HAVE_MMAP) && (defined(__x86_64__) || defined(__aarch64__) || \ |
113 | | (defined(__riscv) && __riscv_xlen == 64)) |
114 | 0 | if (Pointer == nullptr) { |
115 | 0 | return; |
116 | 0 | } |
117 | 0 | munmap(Pointer - k4G, k12G); |
118 | | #else |
119 | | return std::free(Pointer); |
120 | | #endif |
121 | 0 | } |
122 | | |
123 | 0 | uint8_t *Allocator::allocate_chunk(uint64_t Size) noexcept { |
124 | | #if WASMEDGE_OS_WINDOWS |
125 | | if (auto Pointer = winapi::VirtualAlloc(nullptr, Size, winapi::MEM_COMMIT_, |
126 | | winapi::PAGE_READWRITE_); |
127 | | unlikely(Pointer == nullptr)) { |
128 | | return nullptr; |
129 | | } else { |
130 | | return reinterpret_cast<uint8_t *>(Pointer); |
131 | | } |
132 | | #elif defined(HAVE_MMAP) |
133 | | if (auto Pointer = mmap(nullptr, Size, PROT_READ | PROT_WRITE, |
134 | 0 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
135 | 0 | unlikely(Pointer == MAP_FAILED)) { |
136 | 0 | return nullptr; |
137 | 0 | } else { |
138 | 0 | return reinterpret_cast<uint8_t *>(Pointer); |
139 | 0 | } |
140 | | #else |
141 | | return std::malloc(Size); |
142 | | #endif |
143 | 0 | } |
144 | | |
145 | | void Allocator::release_chunk(uint8_t *Pointer, |
146 | 0 | uint64_t Size [[maybe_unused]]) noexcept { |
147 | | #if WASMEDGE_OS_WINDOWS |
148 | | winapi::VirtualFree(Pointer, 0, winapi::MEM_RELEASE_); |
149 | | #elif defined(HAVE_MMAP) |
150 | | munmap(Pointer, Size); |
151 | | #else |
152 | | return std::free(Pointer); |
153 | | #endif |
154 | 0 | } |
155 | | |
156 | 0 | bool Allocator::set_chunk_executable(uint8_t *Pointer, uint64_t Size) noexcept { |
157 | | #if WASMEDGE_OS_WINDOWS |
158 | | winapi::DWORD_ OldPerm; |
159 | | return winapi::VirtualProtect(Pointer, Size, winapi::PAGE_EXECUTE_READ_, |
160 | | &OldPerm) != 0; |
161 | | #elif defined(HAVE_MMAP) |
162 | | return mprotect(Pointer, Size, PROT_EXEC | PROT_READ) == 0; |
163 | | #else |
164 | | return true; |
165 | | #endif |
166 | 0 | } |
167 | | |
168 | 0 | bool Allocator::set_chunk_readable(uint8_t *Pointer, uint64_t Size) noexcept { |
169 | | #if WASMEDGE_OS_WINDOWS |
170 | | winapi::DWORD_ OldPerm; |
171 | | return winapi::VirtualProtect(Pointer, Size, winapi::PAGE_READONLY_, |
172 | | &OldPerm) != 0; |
173 | | #elif defined(HAVE_MMAP) |
174 | | return mprotect(Pointer, Size, PROT_READ) == 0; |
175 | | #else |
176 | | return true; |
177 | | #endif |
178 | 0 | } |
179 | | |
180 | | bool Allocator::set_chunk_readable_writable(uint8_t *Pointer, |
181 | 0 | uint64_t Size) noexcept { |
182 | | #if WASMEDGE_OS_WINDOWS |
183 | | winapi::DWORD_ OldPerm; |
184 | | return winapi::VirtualProtect(Pointer, Size, winapi::PAGE_READWRITE_, |
185 | | &OldPerm) != 0; |
186 | | #elif defined(HAVE_MMAP) |
187 | | return mprotect(Pointer, Size, PROT_READ | PROT_WRITE) == 0; |
188 | | #else |
189 | | return true; |
190 | | #endif |
191 | 0 | } |
192 | | |
193 | | } // namespace WasmEdge |