Path: blob/master/src/hotspot/os/windows/gc/z/zMapper_windows.cpp
40948 views
/*1* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"24#include "gc/z/zMapper_windows.hpp"25#include "gc/z/zSyscall_windows.hpp"26#include "logging/log.hpp"27#include "utilities/debug.hpp"2829#include <Windows.h>3031// Memory reservation, commit, views, and placeholders.32//33// To be able to up-front reserve address space for the heap views, and later34// multi-map the heap views to the same physical memory, without ever losing the35// reservation of the reserved address space, we use "placeholders".36//37// These placeholders block out the address space from being used by other parts38// of the process. To commit memory in this address space, the placeholder must39// be replaced by anonymous memory, or replaced by mapping a view against a40// paging file mapping. We use the later to support multi-mapping.41//42// We want to be able to dynamically commit and uncommit the physical memory of43// the heap (and also unmap ZPages), in granules of ZGranuleSize bytes. There is44// no way to grow and shrink the committed memory of a paging file mapping.45// Therefore, we create multiple granule-sized page file mappings. The memory is46// committed by creating a page file mapping, map a view against it, commit the47// memory, unmap the view. The memory will stay committed until all views are48// unmapped, and the paging file mapping handle is closed.49//50// When replacing a placeholder address space reservation with a mapped view51// against a paging file mapping, the virtual address space must exactly match52// an existing placeholder's address and size. Therefore we only deal with53// granule-sized placeholders at this layer. Higher layers that keep track of54// reserved available address space can (and will) coalesce placeholders, but55// they will be split before being used.5657#define fatal_error(msg, addr, size) \58fatal(msg ": " PTR_FORMAT " " SIZE_FORMAT "M (%d)", \59(addr), (size) / M, GetLastError())6061uintptr_t ZMapper::reserve(uintptr_t addr, size_t size) {62void* const res = ZSyscall::VirtualAlloc2(63GetCurrentProcess(), // Process64(void*)addr, // BaseAddress65size, // Size66MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, // AllocationType67PAGE_NOACCESS, // PageProtection68NULL, // ExtendedParameters690 // ParameterCount70);7172// Caller responsible for error handling73return (uintptr_t)res;74}7576void ZMapper::unreserve(uintptr_t addr, size_t size) {77const bool res = ZSyscall::VirtualFreeEx(78GetCurrentProcess(), // hProcess79(void*)addr, // lpAddress80size, // dwSize81MEM_RELEASE // dwFreeType82);8384if (!res) {85fatal_error("Failed to unreserve memory", addr, size);86}87}8889HANDLE ZMapper::create_paging_file_mapping(size_t size) {90// Create mapping with SEC_RESERVE instead of SEC_COMMIT.91//92// We use MapViewOfFile3 for two different reasons:93// 1) When commiting memory for the created paging file94// 2) When mapping a view of the memory created in (2)95//96// The non-platform code is only setup to deal with out-of-memory97// errors in (1). By using SEC_RESERVE, we prevent MapViewOfFile398// from failing because of "commit limit" checks. To actually commit99// memory in (1), a call to VirtualAlloc2 is done.100101HANDLE const res = ZSyscall::CreateFileMappingW(102INVALID_HANDLE_VALUE, // hFile103NULL, // lpFileMappingAttribute104PAGE_READWRITE | SEC_RESERVE, // flProtect105size >> 32, // dwMaximumSizeHigh106size & 0xFFFFFFFF, // dwMaximumSizeLow107NULL // lpName108);109110// Caller responsible for error handling111return res;112}113114bool ZMapper::commit_paging_file_mapping(HANDLE file_handle, uintptr_t file_offset, size_t size) {115const uintptr_t addr = map_view_no_placeholder(file_handle, file_offset, size);116if (addr == 0) {117log_error(gc)("Failed to map view of paging file mapping (%d)", GetLastError());118return false;119}120121const uintptr_t res = commit(addr, size);122if (res != addr) {123log_error(gc)("Failed to commit memory (%d)", GetLastError());124}125126unmap_view_no_placeholder(addr, size);127128return res == addr;129}130131uintptr_t ZMapper::map_view_no_placeholder(HANDLE file_handle, uintptr_t file_offset, size_t size) {132void* const res = ZSyscall::MapViewOfFile3(133file_handle, // FileMapping134GetCurrentProcess(), // ProcessHandle135NULL, // BaseAddress136file_offset, // Offset137size, // ViewSize1380, // AllocationType139PAGE_NOACCESS, // PageProtection140NULL, // ExtendedParameters1410 // ParameterCount142);143144// Caller responsible for error handling145return (uintptr_t)res;146}147148void ZMapper::unmap_view_no_placeholder(uintptr_t addr, size_t size) {149const bool res = ZSyscall::UnmapViewOfFile2(150GetCurrentProcess(), // ProcessHandle151(void*)addr, // BaseAddress1520 // UnmapFlags153);154155if (!res) {156fatal_error("Failed to unmap memory", addr, size);157}158}159160uintptr_t ZMapper::commit(uintptr_t addr, size_t size) {161void* const res = ZSyscall::VirtualAlloc2(162GetCurrentProcess(), // Process163(void*)addr, // BaseAddress164size, // Size165MEM_COMMIT, // AllocationType166PAGE_NOACCESS, // PageProtection167NULL, // ExtendedParameters1680 // ParameterCount169);170171// Caller responsible for error handling172return (uintptr_t)res;173}174175HANDLE ZMapper::create_and_commit_paging_file_mapping(size_t size) {176HANDLE const file_handle = create_paging_file_mapping(size);177if (file_handle == 0) {178log_error(gc)("Failed to create paging file mapping (%d)", GetLastError());179return 0;180}181182const bool res = commit_paging_file_mapping(file_handle, 0 /* file_offset */, size);183if (!res) {184close_paging_file_mapping(file_handle);185return 0;186}187188return file_handle;189}190191void ZMapper::close_paging_file_mapping(HANDLE file_handle) {192const bool res = CloseHandle(193file_handle // hObject194);195196if (!res) {197fatal("Failed to close paging file handle (%d)", GetLastError());198}199}200201HANDLE ZMapper::create_shared_awe_section() {202MEM_EXTENDED_PARAMETER parameter = { 0 };203parameter.Type = MemSectionExtendedParameterUserPhysicalFlags;204parameter.ULong64 = 0;205206HANDLE section = ZSyscall::CreateFileMapping2(207INVALID_HANDLE_VALUE, // File208NULL, // SecurityAttributes209SECTION_MAP_READ | SECTION_MAP_WRITE, // DesiredAccess210PAGE_READWRITE, // PageProtection211SEC_RESERVE | SEC_LARGE_PAGES, // AllocationAttributes2120, // MaximumSize213NULL, // Name214¶meter, // ExtendedParameters2151 // ParameterCount216);217218if (section == NULL) {219fatal("Could not create shared AWE section (%d)", GetLastError());220}221222return section;223}224225uintptr_t ZMapper::reserve_for_shared_awe(HANDLE awe_section, uintptr_t addr, size_t size) {226MEM_EXTENDED_PARAMETER parameter = { 0 };227parameter.Type = MemExtendedParameterUserPhysicalHandle;228parameter.Handle = awe_section;229230void* const res = ZSyscall::VirtualAlloc2(231GetCurrentProcess(), // Process232(void*)addr, // BaseAddress233size, // Size234MEM_RESERVE | MEM_PHYSICAL, // AllocationType235PAGE_READWRITE, // PageProtection236¶meter, // ExtendedParameters2371 // ParameterCount238);239240// Caller responsible for error handling241return (uintptr_t)res;242}243244void ZMapper::unreserve_for_shared_awe(uintptr_t addr, size_t size) {245bool res = VirtualFree(246(void*)addr, // lpAddress2470, // dwSize248MEM_RELEASE // dwFreeType249);250251if (!res) {252fatal("Failed to unreserve memory: " PTR_FORMAT " " SIZE_FORMAT "M (%d)",253addr, size / M, GetLastError());254}255}256257void ZMapper::split_placeholder(uintptr_t addr, size_t size) {258const bool res = VirtualFree(259(void*)addr, // lpAddress260size, // dwSize261MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER // dwFreeType262);263264if (!res) {265fatal_error("Failed to split placeholder", addr, size);266}267}268269void ZMapper::coalesce_placeholders(uintptr_t addr, size_t size) {270const bool res = VirtualFree(271(void*)addr, // lpAddress272size, // dwSize273MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS // dwFreeType274);275276if (!res) {277fatal_error("Failed to coalesce placeholders", addr, size);278}279}280281void ZMapper::map_view_replace_placeholder(HANDLE file_handle, uintptr_t file_offset, uintptr_t addr, size_t size) {282void* const res = ZSyscall::MapViewOfFile3(283file_handle, // FileMapping284GetCurrentProcess(), // ProcessHandle285(void*)addr, // BaseAddress286file_offset, // Offset287size, // ViewSize288MEM_REPLACE_PLACEHOLDER, // AllocationType289PAGE_READWRITE, // PageProtection290NULL, // ExtendedParameters2910 // ParameterCount292);293294if (res == NULL) {295fatal_error("Failed to map memory", addr, size);296}297}298299void ZMapper::unmap_view_preserve_placeholder(uintptr_t addr, size_t size) {300const bool res = ZSyscall::UnmapViewOfFile2(301GetCurrentProcess(), // ProcessHandle302(void*)addr, // BaseAddress303MEM_PRESERVE_PLACEHOLDER // UnmapFlags304);305306if (!res) {307fatal_error("Failed to unmap memory", addr, size);308}309}310311312