Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/os/windows/gc/z/zMapper_windows.cpp
40948 views
1
/*
2
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
#include "precompiled.hpp"
25
#include "gc/z/zMapper_windows.hpp"
26
#include "gc/z/zSyscall_windows.hpp"
27
#include "logging/log.hpp"
28
#include "utilities/debug.hpp"
29
30
#include <Windows.h>
31
32
// Memory reservation, commit, views, and placeholders.
33
//
34
// To be able to up-front reserve address space for the heap views, and later
35
// multi-map the heap views to the same physical memory, without ever losing the
36
// reservation of the reserved address space, we use "placeholders".
37
//
38
// These placeholders block out the address space from being used by other parts
39
// of the process. To commit memory in this address space, the placeholder must
40
// be replaced by anonymous memory, or replaced by mapping a view against a
41
// paging file mapping. We use the later to support multi-mapping.
42
//
43
// We want to be able to dynamically commit and uncommit the physical memory of
44
// the heap (and also unmap ZPages), in granules of ZGranuleSize bytes. There is
45
// no way to grow and shrink the committed memory of a paging file mapping.
46
// Therefore, we create multiple granule-sized page file mappings. The memory is
47
// committed by creating a page file mapping, map a view against it, commit the
48
// memory, unmap the view. The memory will stay committed until all views are
49
// unmapped, and the paging file mapping handle is closed.
50
//
51
// When replacing a placeholder address space reservation with a mapped view
52
// against a paging file mapping, the virtual address space must exactly match
53
// an existing placeholder's address and size. Therefore we only deal with
54
// granule-sized placeholders at this layer. Higher layers that keep track of
55
// reserved available address space can (and will) coalesce placeholders, but
56
// they will be split before being used.
57
58
#define fatal_error(msg, addr, size) \
59
fatal(msg ": " PTR_FORMAT " " SIZE_FORMAT "M (%d)", \
60
(addr), (size) / M, GetLastError())
61
62
uintptr_t ZMapper::reserve(uintptr_t addr, size_t size) {
63
void* const res = ZSyscall::VirtualAlloc2(
64
GetCurrentProcess(), // Process
65
(void*)addr, // BaseAddress
66
size, // Size
67
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, // AllocationType
68
PAGE_NOACCESS, // PageProtection
69
NULL, // ExtendedParameters
70
0 // ParameterCount
71
);
72
73
// Caller responsible for error handling
74
return (uintptr_t)res;
75
}
76
77
void ZMapper::unreserve(uintptr_t addr, size_t size) {
78
const bool res = ZSyscall::VirtualFreeEx(
79
GetCurrentProcess(), // hProcess
80
(void*)addr, // lpAddress
81
size, // dwSize
82
MEM_RELEASE // dwFreeType
83
);
84
85
if (!res) {
86
fatal_error("Failed to unreserve memory", addr, size);
87
}
88
}
89
90
HANDLE ZMapper::create_paging_file_mapping(size_t size) {
91
// Create mapping with SEC_RESERVE instead of SEC_COMMIT.
92
//
93
// We use MapViewOfFile3 for two different reasons:
94
// 1) When commiting memory for the created paging file
95
// 2) When mapping a view of the memory created in (2)
96
//
97
// The non-platform code is only setup to deal with out-of-memory
98
// errors in (1). By using SEC_RESERVE, we prevent MapViewOfFile3
99
// from failing because of "commit limit" checks. To actually commit
100
// memory in (1), a call to VirtualAlloc2 is done.
101
102
HANDLE const res = ZSyscall::CreateFileMappingW(
103
INVALID_HANDLE_VALUE, // hFile
104
NULL, // lpFileMappingAttribute
105
PAGE_READWRITE | SEC_RESERVE, // flProtect
106
size >> 32, // dwMaximumSizeHigh
107
size & 0xFFFFFFFF, // dwMaximumSizeLow
108
NULL // lpName
109
);
110
111
// Caller responsible for error handling
112
return res;
113
}
114
115
bool ZMapper::commit_paging_file_mapping(HANDLE file_handle, uintptr_t file_offset, size_t size) {
116
const uintptr_t addr = map_view_no_placeholder(file_handle, file_offset, size);
117
if (addr == 0) {
118
log_error(gc)("Failed to map view of paging file mapping (%d)", GetLastError());
119
return false;
120
}
121
122
const uintptr_t res = commit(addr, size);
123
if (res != addr) {
124
log_error(gc)("Failed to commit memory (%d)", GetLastError());
125
}
126
127
unmap_view_no_placeholder(addr, size);
128
129
return res == addr;
130
}
131
132
uintptr_t ZMapper::map_view_no_placeholder(HANDLE file_handle, uintptr_t file_offset, size_t size) {
133
void* const res = ZSyscall::MapViewOfFile3(
134
file_handle, // FileMapping
135
GetCurrentProcess(), // ProcessHandle
136
NULL, // BaseAddress
137
file_offset, // Offset
138
size, // ViewSize
139
0, // AllocationType
140
PAGE_NOACCESS, // PageProtection
141
NULL, // ExtendedParameters
142
0 // ParameterCount
143
);
144
145
// Caller responsible for error handling
146
return (uintptr_t)res;
147
}
148
149
void ZMapper::unmap_view_no_placeholder(uintptr_t addr, size_t size) {
150
const bool res = ZSyscall::UnmapViewOfFile2(
151
GetCurrentProcess(), // ProcessHandle
152
(void*)addr, // BaseAddress
153
0 // UnmapFlags
154
);
155
156
if (!res) {
157
fatal_error("Failed to unmap memory", addr, size);
158
}
159
}
160
161
uintptr_t ZMapper::commit(uintptr_t addr, size_t size) {
162
void* const res = ZSyscall::VirtualAlloc2(
163
GetCurrentProcess(), // Process
164
(void*)addr, // BaseAddress
165
size, // Size
166
MEM_COMMIT, // AllocationType
167
PAGE_NOACCESS, // PageProtection
168
NULL, // ExtendedParameters
169
0 // ParameterCount
170
);
171
172
// Caller responsible for error handling
173
return (uintptr_t)res;
174
}
175
176
HANDLE ZMapper::create_and_commit_paging_file_mapping(size_t size) {
177
HANDLE const file_handle = create_paging_file_mapping(size);
178
if (file_handle == 0) {
179
log_error(gc)("Failed to create paging file mapping (%d)", GetLastError());
180
return 0;
181
}
182
183
const bool res = commit_paging_file_mapping(file_handle, 0 /* file_offset */, size);
184
if (!res) {
185
close_paging_file_mapping(file_handle);
186
return 0;
187
}
188
189
return file_handle;
190
}
191
192
void ZMapper::close_paging_file_mapping(HANDLE file_handle) {
193
const bool res = CloseHandle(
194
file_handle // hObject
195
);
196
197
if (!res) {
198
fatal("Failed to close paging file handle (%d)", GetLastError());
199
}
200
}
201
202
HANDLE ZMapper::create_shared_awe_section() {
203
MEM_EXTENDED_PARAMETER parameter = { 0 };
204
parameter.Type = MemSectionExtendedParameterUserPhysicalFlags;
205
parameter.ULong64 = 0;
206
207
HANDLE section = ZSyscall::CreateFileMapping2(
208
INVALID_HANDLE_VALUE, // File
209
NULL, // SecurityAttributes
210
SECTION_MAP_READ | SECTION_MAP_WRITE, // DesiredAccess
211
PAGE_READWRITE, // PageProtection
212
SEC_RESERVE | SEC_LARGE_PAGES, // AllocationAttributes
213
0, // MaximumSize
214
NULL, // Name
215
&parameter, // ExtendedParameters
216
1 // ParameterCount
217
);
218
219
if (section == NULL) {
220
fatal("Could not create shared AWE section (%d)", GetLastError());
221
}
222
223
return section;
224
}
225
226
uintptr_t ZMapper::reserve_for_shared_awe(HANDLE awe_section, uintptr_t addr, size_t size) {
227
MEM_EXTENDED_PARAMETER parameter = { 0 };
228
parameter.Type = MemExtendedParameterUserPhysicalHandle;
229
parameter.Handle = awe_section;
230
231
void* const res = ZSyscall::VirtualAlloc2(
232
GetCurrentProcess(), // Process
233
(void*)addr, // BaseAddress
234
size, // Size
235
MEM_RESERVE | MEM_PHYSICAL, // AllocationType
236
PAGE_READWRITE, // PageProtection
237
&parameter, // ExtendedParameters
238
1 // ParameterCount
239
);
240
241
// Caller responsible for error handling
242
return (uintptr_t)res;
243
}
244
245
void ZMapper::unreserve_for_shared_awe(uintptr_t addr, size_t size) {
246
bool res = VirtualFree(
247
(void*)addr, // lpAddress
248
0, // dwSize
249
MEM_RELEASE // dwFreeType
250
);
251
252
if (!res) {
253
fatal("Failed to unreserve memory: " PTR_FORMAT " " SIZE_FORMAT "M (%d)",
254
addr, size / M, GetLastError());
255
}
256
}
257
258
void ZMapper::split_placeholder(uintptr_t addr, size_t size) {
259
const bool res = VirtualFree(
260
(void*)addr, // lpAddress
261
size, // dwSize
262
MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER // dwFreeType
263
);
264
265
if (!res) {
266
fatal_error("Failed to split placeholder", addr, size);
267
}
268
}
269
270
void ZMapper::coalesce_placeholders(uintptr_t addr, size_t size) {
271
const bool res = VirtualFree(
272
(void*)addr, // lpAddress
273
size, // dwSize
274
MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS // dwFreeType
275
);
276
277
if (!res) {
278
fatal_error("Failed to coalesce placeholders", addr, size);
279
}
280
}
281
282
void ZMapper::map_view_replace_placeholder(HANDLE file_handle, uintptr_t file_offset, uintptr_t addr, size_t size) {
283
void* const res = ZSyscall::MapViewOfFile3(
284
file_handle, // FileMapping
285
GetCurrentProcess(), // ProcessHandle
286
(void*)addr, // BaseAddress
287
file_offset, // Offset
288
size, // ViewSize
289
MEM_REPLACE_PLACEHOLDER, // AllocationType
290
PAGE_READWRITE, // PageProtection
291
NULL, // ExtendedParameters
292
0 // ParameterCount
293
);
294
295
if (res == NULL) {
296
fatal_error("Failed to map memory", addr, size);
297
}
298
}
299
300
void ZMapper::unmap_view_preserve_placeholder(uintptr_t addr, size_t size) {
301
const bool res = ZSyscall::UnmapViewOfFile2(
302
GetCurrentProcess(), // ProcessHandle
303
(void*)addr, // BaseAddress
304
MEM_PRESERVE_PLACEHOLDER // UnmapFlags
305
);
306
307
if (!res) {
308
fatal_error("Failed to unmap memory", addr, size);
309
}
310
}
311
312