Path: blob/master/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp
40948 views
/*1* Copyright (c) 2019, 2020, 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/zGlobals.hpp"25#include "gc/z/zGranuleMap.inline.hpp"26#include "gc/z/zLargePages.inline.hpp"27#include "gc/z/zMapper_windows.hpp"28#include "gc/z/zPhysicalMemoryBacking_windows.hpp"29#include "logging/log.hpp"30#include "runtime/globals.hpp"31#include "utilities/debug.hpp"3233class ZPhysicalMemoryBackingImpl : public CHeapObj<mtGC> {34public:35virtual size_t commit(size_t offset, size_t size) = 0;36virtual size_t uncommit(size_t offset, size_t size) = 0;37virtual void map(uintptr_t addr, size_t size, size_t offset) const = 0;38virtual void unmap(uintptr_t addr, size_t size) const = 0;39};4041// Implements small pages (paged) support using placeholder reservation.42//43// The backing commits and uncommits physical memory, that can be44// multi-mapped into the virtual address space. To support fine-graned45// committing and uncommitting, each ZGranuleSize'd chunk is mapped to46// a separate paging file mapping.4748class ZPhysicalMemoryBackingSmallPages : public ZPhysicalMemoryBackingImpl {49private:50ZGranuleMap<HANDLE> _handles;5152HANDLE get_handle(uintptr_t offset) const {53HANDLE const handle = _handles.get(offset);54assert(handle != 0, "Should be set");55return handle;56}5758void put_handle(uintptr_t offset, HANDLE handle) {59assert(handle != INVALID_HANDLE_VALUE, "Invalid handle");60assert(_handles.get(offset) == 0, "Should be cleared");61_handles.put(offset, handle);62}6364void clear_handle(uintptr_t offset) {65assert(_handles.get(offset) != 0, "Should be set");66_handles.put(offset, 0);67}6869public:70ZPhysicalMemoryBackingSmallPages(size_t max_capacity) :71ZPhysicalMemoryBackingImpl(),72_handles(max_capacity) {}7374size_t commit(size_t offset, size_t size) {75for (size_t i = 0; i < size; i += ZGranuleSize) {76HANDLE const handle = ZMapper::create_and_commit_paging_file_mapping(ZGranuleSize);77if (handle == 0) {78return i;79}8081put_handle(offset + i, handle);82}8384return size;85}8687size_t uncommit(size_t offset, size_t size) {88for (size_t i = 0; i < size; i += ZGranuleSize) {89HANDLE const handle = get_handle(offset + i);90clear_handle(offset + i);91ZMapper::close_paging_file_mapping(handle);92}9394return size;95}9697void map(uintptr_t addr, size_t size, size_t offset) const {98assert(is_aligned(offset, ZGranuleSize), "Misaligned");99assert(is_aligned(addr, ZGranuleSize), "Misaligned");100assert(is_aligned(size, ZGranuleSize), "Misaligned");101102for (size_t i = 0; i < size; i += ZGranuleSize) {103HANDLE const handle = get_handle(offset + i);104ZMapper::map_view_replace_placeholder(handle, 0 /* offset */, addr + i, ZGranuleSize);105}106}107108void unmap(uintptr_t addr, size_t size) const {109assert(is_aligned(addr, ZGranuleSize), "Misaligned");110assert(is_aligned(size, ZGranuleSize), "Misaligned");111112for (size_t i = 0; i < size; i += ZGranuleSize) {113ZMapper::unmap_view_preserve_placeholder(addr + i, ZGranuleSize);114}115}116};117118// Implements Large Pages (locked) support using shared AWE physical memory.119//120// Shared AWE physical memory also works with small pages, but it has121// a few drawbacks that makes it a no-go to use it at this point:122//123// 1) It seems to use 8 bytes of committed memory per *reserved* memory.124// Given our scheme to use a large address space range this turns out to125// use too much memory.126//127// 2) It requires memory locking privilages, even for small pages. This128// has always been a requirement for large pages, and would be an extra129// restriction for usage with small pages.130//131// Note: The large pages size is tied to our ZGranuleSize.132133extern HANDLE ZAWESection;134135class ZPhysicalMemoryBackingLargePages : public ZPhysicalMemoryBackingImpl {136private:137ULONG_PTR* const _page_array;138139static ULONG_PTR* alloc_page_array(size_t max_capacity) {140const size_t npages = max_capacity / ZGranuleSize;141const size_t array_size = npages * sizeof(ULONG_PTR);142143return (ULONG_PTR*)os::malloc(array_size, mtGC);144}145146public:147ZPhysicalMemoryBackingLargePages(size_t max_capacity) :148ZPhysicalMemoryBackingImpl(),149_page_array(alloc_page_array(max_capacity)) {}150151size_t commit(size_t offset, size_t size) {152const size_t index = offset >> ZGranuleSizeShift;153const size_t npages = size >> ZGranuleSizeShift;154155size_t npages_res = npages;156const bool res = AllocateUserPhysicalPages(ZAWESection, &npages_res, &_page_array[index]);157if (!res) {158fatal("Failed to allocate physical memory " SIZE_FORMAT "M @ " PTR_FORMAT " (%d)",159size / M, offset, GetLastError());160} else {161log_debug(gc)("Allocated physical memory: " SIZE_FORMAT "M @ " PTR_FORMAT, size / M, offset);162}163164// AllocateUserPhysicalPages might not be able to allocate the requested amount of memory.165// The allocated number of pages are written in npages_res.166return npages_res << ZGranuleSizeShift;167}168169size_t uncommit(size_t offset, size_t size) {170const size_t index = offset >> ZGranuleSizeShift;171const size_t npages = size >> ZGranuleSizeShift;172173size_t npages_res = npages;174const bool res = FreeUserPhysicalPages(ZAWESection, &npages_res, &_page_array[index]);175if (!res) {176fatal("Failed to uncommit physical memory " SIZE_FORMAT "M @ " PTR_FORMAT " (%d)",177size, offset, GetLastError());178}179180return npages_res << ZGranuleSizeShift;181}182183void map(uintptr_t addr, size_t size, size_t offset) const {184const size_t npages = size >> ZGranuleSizeShift;185const size_t index = offset >> ZGranuleSizeShift;186187const bool res = MapUserPhysicalPages((char*)addr, npages, &_page_array[index]);188if (!res) {189fatal("Failed to map view " PTR_FORMAT " " SIZE_FORMAT "M @ " PTR_FORMAT " (%d)",190addr, size / M, offset, GetLastError());191}192}193194void unmap(uintptr_t addr, size_t size) const {195const size_t npages = size >> ZGranuleSizeShift;196197const bool res = MapUserPhysicalPages((char*)addr, npages, NULL);198if (!res) {199fatal("Failed to unmap view " PTR_FORMAT " " SIZE_FORMAT "M (%d)",200addr, size / M, GetLastError());201}202}203};204205static ZPhysicalMemoryBackingImpl* select_impl(size_t max_capacity) {206if (ZLargePages::is_enabled()) {207return new ZPhysicalMemoryBackingLargePages(max_capacity);208}209210return new ZPhysicalMemoryBackingSmallPages(max_capacity);211}212213ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity) :214_impl(select_impl(max_capacity)) {}215216bool ZPhysicalMemoryBacking::is_initialized() const {217return true;218}219220void ZPhysicalMemoryBacking::warn_commit_limits(size_t max_capacity) const {221// Does nothing222}223224size_t ZPhysicalMemoryBacking::commit(size_t offset, size_t length) {225log_trace(gc, heap)("Committing memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",226offset / M, (offset + length) / M, length / M);227228return _impl->commit(offset, length);229}230231size_t ZPhysicalMemoryBacking::uncommit(size_t offset, size_t length) {232log_trace(gc, heap)("Uncommitting memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)",233offset / M, (offset + length) / M, length / M);234235return _impl->uncommit(offset, length);236}237238void ZPhysicalMemoryBacking::map(uintptr_t addr, size_t size, size_t offset) const {239assert(is_aligned(offset, ZGranuleSize), "Misaligned: " PTR_FORMAT, offset);240assert(is_aligned(addr, ZGranuleSize), "Misaligned: " PTR_FORMAT, addr);241assert(is_aligned(size, ZGranuleSize), "Misaligned: " PTR_FORMAT, size);242243_impl->map(addr, size, offset);244}245246void ZPhysicalMemoryBacking::unmap(uintptr_t addr, size_t size) const {247assert(is_aligned(addr, ZGranuleSize), "Misaligned");248assert(is_aligned(size, ZGranuleSize), "Misaligned");249250_impl->unmap(addr, size);251}252253254