Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/common/sys/alloc.cpp
9912 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#include "alloc.h"
5
#include "intrinsics.h"
6
#include "sysinfo.h"
7
#include "mutex.h"
8
9
////////////////////////////////////////////////////////////////////////////////
10
/// All Platforms
11
////////////////////////////////////////////////////////////////////////////////
12
13
namespace embree
14
{
15
void* alignedMalloc(size_t size, size_t align)
16
{
17
if (size == 0)
18
return nullptr;
19
20
assert((align & (align-1)) == 0);
21
void* ptr = _mm_malloc(size,align);
22
if (size != 0 && ptr == nullptr)
23
abort(); //throw std::bad_alloc();
24
return ptr;
25
}
26
27
void alignedFree(void* ptr)
28
{
29
if (ptr) {
30
_mm_free(ptr);
31
}
32
}
33
34
#if defined(EMBREE_SYCL_SUPPORT)
35
36
void* alignedSYCLMalloc(sycl::context* context, sycl::device* device, size_t size, size_t align, EmbreeUSMMode mode)
37
{
38
assert(context);
39
assert(device);
40
41
if (size == 0)
42
return nullptr;
43
44
assert((align & (align-1)) == 0);
45
46
void* ptr = nullptr;
47
if (mode == EmbreeUSMMode::DEVICE_READ_ONLY)
48
ptr = sycl::aligned_alloc_shared(align,size,*device,*context,sycl::ext::oneapi::property::usm::device_read_only());
49
else
50
ptr = sycl::aligned_alloc_shared(align,size,*device,*context);
51
52
if (size != 0 && ptr == nullptr)
53
abort(); //throw std::bad_alloc();
54
55
return ptr;
56
}
57
58
void* alignedSYCLMalloc(sycl::context* context, sycl::device* device, size_t size, size_t align, EmbreeUSMMode mode, EmbreeMemoryType type)
59
{
60
assert(context);
61
assert(device);
62
63
if (size == 0)
64
return nullptr;
65
66
assert((align & (align-1)) == 0);
67
68
void* ptr = nullptr;
69
if (type == EmbreeMemoryType::USM_SHARED) {
70
if (mode == EmbreeUSMMode::DEVICE_READ_ONLY)
71
ptr = sycl::aligned_alloc_shared(align,size,*device,*context,sycl::ext::oneapi::property::usm::device_read_only());
72
else
73
ptr = sycl::aligned_alloc_shared(align,size,*device,*context);
74
}
75
else if (type == EmbreeMemoryType::USM_HOST) {
76
ptr = sycl::aligned_alloc_host(align,size,*context);
77
}
78
else if (type == EmbreeMemoryType::USM_DEVICE) {
79
ptr = sycl::aligned_alloc_device(align,size,*device,*context);
80
}
81
else {
82
ptr = alignedMalloc(size,align);
83
}
84
85
if (size != 0 && ptr == nullptr)
86
abort(); //throw std::bad_alloc();
87
88
return ptr;
89
}
90
91
void alignedSYCLFree(sycl::context* context, void* ptr)
92
{
93
assert(context);
94
if (ptr) {
95
sycl::usm::alloc type = sycl::get_pointer_type(ptr, *context);
96
if (type == sycl::usm::alloc::host || type == sycl::usm::alloc::device || type == sycl::usm::alloc::shared)
97
sycl::free(ptr,*context);
98
else {
99
alignedFree(ptr);
100
}
101
}
102
}
103
104
#endif
105
106
static bool huge_pages_enabled = false;
107
static MutexSys os_init_mutex;
108
109
__forceinline bool isHugePageCandidate(const size_t bytes)
110
{
111
if (!huge_pages_enabled)
112
return false;
113
114
/* use huge pages only when memory overhead is low */
115
const size_t hbytes = (bytes+PAGE_SIZE_2M-1) & ~size_t(PAGE_SIZE_2M-1);
116
return 66*(hbytes-bytes) < bytes; // at most 1.5% overhead
117
}
118
}
119
120
////////////////////////////////////////////////////////////////////////////////
121
/// Windows Platform
122
////////////////////////////////////////////////////////////////////////////////
123
124
#ifdef _WIN32
125
126
#define WIN32_LEAN_AND_MEAN
127
#include <windows.h>
128
#include <malloc.h>
129
130
namespace embree
131
{
132
bool win_enable_selockmemoryprivilege (bool verbose)
133
{
134
HANDLE hToken;
135
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) {
136
if (verbose) std::cout << "WARNING: OpenProcessToken failed while trying to enable SeLockMemoryPrivilege: " << GetLastError() << std::endl;
137
return false;
138
}
139
140
TOKEN_PRIVILEGES tp;
141
tp.PrivilegeCount = 1;
142
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
143
144
if (!LookupPrivilegeValueW(nullptr, L"SeLockMemoryPrivilege", &tp.Privileges[0].Luid)) {
145
if (verbose) std::cout << "WARNING: LookupPrivilegeValue failed while trying to enable SeLockMemoryPrivilege: " << GetLastError() << std::endl;
146
return false;
147
}
148
149
SetLastError(ERROR_SUCCESS);
150
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), nullptr, 0)) {
151
if (verbose) std::cout << "WARNING: AdjustTokenPrivileges failed while trying to enable SeLockMemoryPrivilege" << std::endl;
152
return false;
153
}
154
155
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
156
if (verbose) std::cout << "WARNING: AdjustTokenPrivileges failed to enable SeLockMemoryPrivilege: Add SeLockMemoryPrivilege for current user and run process in elevated mode (Run as administrator)." << std::endl;
157
return false;
158
}
159
160
return true;
161
}
162
163
bool os_init(bool hugepages, bool verbose)
164
{
165
Lock<MutexSys> lock(os_init_mutex);
166
167
if (!hugepages) {
168
huge_pages_enabled = false;
169
return true;
170
}
171
172
if (GetLargePageMinimum() != PAGE_SIZE_2M) {
173
huge_pages_enabled = false;
174
return false;
175
}
176
177
huge_pages_enabled = true;
178
return true;
179
}
180
181
void* os_malloc(size_t bytes, bool& hugepages)
182
{
183
if (bytes == 0) {
184
hugepages = false;
185
return nullptr;
186
}
187
188
/* try direct huge page allocation first */
189
if (isHugePageCandidate(bytes))
190
{
191
int flags = MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES;
192
char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
193
if (ptr != nullptr) {
194
hugepages = true;
195
return ptr;
196
}
197
}
198
199
/* fall back to 4k pages */
200
int flags = MEM_COMMIT | MEM_RESERVE;
201
char* ptr = (char*) VirtualAlloc(nullptr,bytes,flags,PAGE_READWRITE);
202
if (ptr == nullptr) abort(); //throw std::bad_alloc();
203
hugepages = false;
204
return ptr;
205
}
206
207
size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld, bool hugepages)
208
{
209
if (hugepages) // decommitting huge pages seems not to work under Windows
210
return bytesOld;
211
212
const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
213
bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);
214
bytesOld = (bytesOld+pageSize-1) & ~(pageSize-1);
215
if (bytesNew >= bytesOld)
216
return bytesOld;
217
218
if (!VirtualFree((char*)ptr+bytesNew,bytesOld-bytesNew,MEM_DECOMMIT))
219
abort(); //throw std::bad_alloc();
220
221
return bytesNew;
222
}
223
224
void os_free(void* ptr, size_t bytes, bool hugepages)
225
{
226
if (bytes == 0)
227
return;
228
229
if (!VirtualFree(ptr,0,MEM_RELEASE))
230
abort(); //throw std::bad_alloc();
231
}
232
233
void os_advise(void *ptr, size_t bytes)
234
{
235
}
236
}
237
238
#endif
239
240
////////////////////////////////////////////////////////////////////////////////
241
/// Unix Platform
242
////////////////////////////////////////////////////////////////////////////////
243
244
#if defined(__UNIX__)
245
246
#include <sys/mman.h>
247
#include <errno.h>
248
#include <stdlib.h>
249
#include <string.h>
250
#include <sstream>
251
252
#if defined(__MACOSX__)
253
#include <mach/vm_statistics.h>
254
#endif
255
256
namespace embree
257
{
258
bool os_init(bool hugepages, bool verbose)
259
{
260
Lock<MutexSys> lock(os_init_mutex);
261
262
if (!hugepages) {
263
huge_pages_enabled = false;
264
return true;
265
}
266
267
#if defined(__LINUX__)
268
269
int hugepagesize = 0;
270
271
std::ifstream file;
272
file.open("/proc/meminfo",std::ios::in);
273
if (!file.is_open()) {
274
if (verbose) std::cout << "WARNING: Could not open /proc/meminfo. Huge page support cannot get enabled!" << std::endl;
275
huge_pages_enabled = false;
276
return false;
277
}
278
279
std::string line;
280
while (getline(file,line))
281
{
282
std::stringstream sline(line);
283
while (!sline.eof() && sline.peek() == ' ') sline.ignore();
284
std::string tag; getline(sline,tag,' ');
285
while (!sline.eof() && sline.peek() == ' ') sline.ignore();
286
std::string val; getline(sline,val,' ');
287
while (!sline.eof() && sline.peek() == ' ') sline.ignore();
288
std::string unit; getline(sline,unit,' ');
289
if (tag == "Hugepagesize:" && unit == "kB") {
290
hugepagesize = std::stoi(val)*1024;
291
break;
292
}
293
}
294
295
if (hugepagesize != PAGE_SIZE_2M)
296
{
297
if (verbose) std::cout << "WARNING: Only 2MB huge pages supported. Huge page support cannot get enabled!" << std::endl;
298
huge_pages_enabled = false;
299
return false;
300
}
301
#endif
302
303
huge_pages_enabled = true;
304
return true;
305
}
306
307
void* os_malloc(size_t bytes, bool& hugepages)
308
{
309
if (bytes == 0) {
310
hugepages = false;
311
return nullptr;
312
}
313
314
/* try direct huge page allocation first */
315
if (isHugePageCandidate(bytes))
316
{
317
#if defined(__MACOSX__)
318
void* ptr = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
319
if (ptr != MAP_FAILED) {
320
hugepages = true;
321
return ptr;
322
}
323
#elif defined(MAP_HUGETLB)
324
void* ptr = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_HUGETLB, -1, 0);
325
if (ptr != MAP_FAILED) {
326
hugepages = true;
327
return ptr;
328
}
329
#endif
330
}
331
332
/* fallback to 4k pages */
333
void* ptr = (char*) mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
334
if (ptr == MAP_FAILED) abort(); //throw std::bad_alloc();
335
hugepages = false;
336
337
/* advise huge page hint for THP */
338
os_advise(ptr,bytes);
339
return ptr;
340
}
341
342
size_t os_shrink(void* ptr, size_t bytesNew, size_t bytesOld, bool hugepages)
343
{
344
const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
345
bytesNew = (bytesNew+pageSize-1) & ~(pageSize-1);
346
bytesOld = (bytesOld+pageSize-1) & ~(pageSize-1);
347
if (bytesNew >= bytesOld)
348
return bytesOld;
349
350
if (munmap((char*)ptr+bytesNew,bytesOld-bytesNew) == -1)
351
abort(); //throw std::bad_alloc();
352
353
return bytesNew;
354
}
355
356
void os_free(void* ptr, size_t bytes, bool hugepages)
357
{
358
if (bytes == 0)
359
return;
360
361
/* for hugepages we need to also align the size */
362
const size_t pageSize = hugepages ? PAGE_SIZE_2M : PAGE_SIZE_4K;
363
bytes = (bytes+pageSize-1) & ~(pageSize-1);
364
if (munmap(ptr,bytes) == -1)
365
abort(); //throw std::bad_alloc();
366
}
367
368
/* hint for transparent huge pages (THP) */
369
void os_advise(void* pptr, size_t bytes)
370
{
371
#if defined(MADV_HUGEPAGE)
372
madvise(pptr,bytes,MADV_HUGEPAGE);
373
#endif
374
}
375
}
376
377
#endif
378
379