Path: blob/master/src/java.base/share/classes/java/nio/MappedMemoryUtils.java
41152 views
/*1* Copyright (c) 2020, 2021, 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. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.nio;2627import jdk.internal.misc.Unsafe;2829import java.io.FileDescriptor;30import java.io.IOException;31import java.io.UncheckedIOException;3233/* package */ class MappedMemoryUtils {3435static boolean isLoaded(long address, boolean isSync, long size) {36// a sync mapped buffer is always loaded37if (isSync) {38return true;39}40if ((address == 0) || (size == 0))41return true;42long offset = mappingOffset(address);43long length = mappingLength(offset, size);44return isLoaded0(mappingAddress(address, offset), length, Bits.pageCount(length));45}4647static void load(long address, boolean isSync, long size) {48// no need to load a sync mapped buffer49if (isSync) {50return;51}52if ((address == 0) || (size == 0))53return;54long offset = mappingOffset(address);55long length = mappingLength(offset, size);56load0(mappingAddress(address, offset), length);5758// Read a byte from each page to bring it into memory. A checksum59// is computed as we go along to prevent the compiler from otherwise60// considering the loop as dead code.61Unsafe unsafe = Unsafe.getUnsafe();62int ps = Bits.pageSize();63long count = Bits.pageCount(length);64long a = mappingAddress(address, offset);65byte x = 0;66for (long i=0; i<count; i++) {67// TODO consider changing to getByteOpaque thus avoiding68// dead code elimination and the need to calculate a checksum69x ^= unsafe.getByte(a);70a += ps;71}72if (unused != 0)73unused = x;74}7576// not used, but a potential target for a store, see load() for details.77private static byte unused;7879static void unload(long address, boolean isSync, long size) {80// no need to load a sync mapped buffer81if (isSync) {82return;83}84if ((address == 0) || (size == 0))85return;86long offset = mappingOffset(address);87long length = mappingLength(offset, size);88unload0(mappingAddress(address, offset), length);89}9091static void force(FileDescriptor fd, long address, boolean isSync, long index, long length) {92if (isSync) {93// simply force writeback of associated cache lines94Unsafe.getUnsafe().writebackMemory(address + index, length);95} else {96// force writeback via file descriptor97long offset = mappingOffset(address, index);98try {99force0(fd, mappingAddress(address, offset, index), mappingLength(offset, length));100} catch (IOException cause) {101throw new UncheckedIOException(cause);102}103}104}105106// native methods107108private static native boolean isLoaded0(long address, long length, long pageCount);109private static native void load0(long address, long length);110private static native void unload0(long address, long length);111private static native void force0(FileDescriptor fd, long address, long length) throws IOException;112113// utility methods114115// Returns the distance (in bytes) of the buffer start from the116// largest page aligned address of the mapping less than or equal117// to the start address.118private static long mappingOffset(long address) {119return mappingOffset(address, 0);120}121122// Returns the distance (in bytes) of the buffer element123// identified by index from the largest page aligned address of124// the mapping less than or equal to the element address. Computed125// each time to avoid storing in every direct buffer.126private static long mappingOffset(long address, long index) {127int ps = Bits.pageSize();128long indexAddress = address + index;129long baseAddress = alignDown(indexAddress, ps);130return indexAddress - baseAddress;131}132133// Given an offset previously obtained from calling134// mappingOffset() returns the largest page aligned address of the135// mapping less than or equal to the buffer start address.136private static long mappingAddress(long address, long mappingOffset) {137return mappingAddress(address, mappingOffset, 0);138}139140// Given an offset previously otained from calling141// mappingOffset(index) returns the largest page aligned address142// of the mapping less than or equal to the address of the buffer143// element identified by index.144private static long mappingAddress(long address, long mappingOffset, long index) {145long indexAddress = address + index;146return indexAddress - mappingOffset;147}148149// given a mappingOffset previously otained from calling150// mappingOffset(index) return that offset added to the supplied151// length.152private static long mappingLength(long mappingOffset, long length) {153return length + mappingOffset;154}155156// align address down to page size157private static long alignDown(long address, int pageSize) {158// pageSize must be a power of 2159return address & ~(pageSize - 1);160}161}162163164