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