|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package java.nio; |
|
|
|
import jdk.internal.misc.Unsafe; |
|
|
|
import java.io.FileDescriptor; |
|
import java.io.IOException; |
|
import java.io.UncheckedIOException; |
|
|
|
class MappedMemoryUtils { |
|
|
|
static boolean isLoaded(long address, boolean isSync, long size) { |
|
|
|
if (isSync) { |
|
return true; |
|
} |
|
if ((address == 0) || (size == 0)) |
|
return true; |
|
long offset = mappingOffset(address); |
|
long length = mappingLength(offset, size); |
|
return isLoaded0(mappingAddress(address, offset), length, Bits.pageCount(length)); |
|
} |
|
|
|
static void load(long address, boolean isSync, long size) { |
|
|
|
if (isSync) { |
|
return; |
|
} |
|
if ((address == 0) || (size == 0)) |
|
return; |
|
long offset = mappingOffset(address); |
|
long length = mappingLength(offset, size); |
|
load0(mappingAddress(address, offset), length); |
|
|
|
// Read a byte from each page to bring it into memory. A checksum |
|
// is computed as we go along to prevent the compiler from otherwise |
|
|
|
Unsafe unsafe = Unsafe.getUnsafe(); |
|
int ps = Bits.pageSize(); |
|
long count = Bits.pageCount(length); |
|
long a = mappingAddress(address, offset); |
|
byte x = 0; |
|
for (long i=0; i<count; i++) { |
|
// TODO consider changing to getByteOpaque thus avoiding |
|
|
|
x ^= unsafe.getByte(a); |
|
a += ps; |
|
} |
|
if (unused != 0) |
|
unused = x; |
|
} |
|
|
|
|
|
private static byte unused; |
|
|
|
static void unload(long address, boolean isSync, long size) { |
|
|
|
if (isSync) { |
|
return; |
|
} |
|
if ((address == 0) || (size == 0)) |
|
return; |
|
long offset = mappingOffset(address); |
|
long length = mappingLength(offset, size); |
|
unload0(mappingAddress(address, offset), length); |
|
} |
|
|
|
static void force(FileDescriptor fd, long address, boolean isSync, long index, long length) { |
|
if (isSync) { |
|
|
|
Unsafe.getUnsafe().writebackMemory(address + index, length); |
|
} else { |
|
|
|
long offset = mappingOffset(address, index); |
|
try { |
|
force0(fd, mappingAddress(address, offset, index), mappingLength(offset, length)); |
|
} catch (IOException cause) { |
|
throw new UncheckedIOException(cause); |
|
} |
|
} |
|
} |
|
|
|
// native methods |
|
|
|
private static native boolean isLoaded0(long address, long length, long pageCount); |
|
private static native void load0(long address, long length); |
|
private static native void unload0(long address, long length); |
|
private static native void force0(FileDescriptor fd, long address, long length) throws IOException; |
|
|
|
// utility methods |
|
|
|
// Returns the distance (in bytes) of the buffer start from the |
|
// largest page aligned address of the mapping less than or equal |
|
|
|
private static long mappingOffset(long address) { |
|
return mappingOffset(address, 0); |
|
} |
|
|
|
// Returns the distance (in bytes) of the buffer element |
|
// identified by index from the largest page aligned address of |
|
// the mapping less than or equal to the element address. Computed |
|
|
|
private static long mappingOffset(long address, long index) { |
|
int ps = Bits.pageSize(); |
|
long indexAddress = address + index; |
|
long baseAddress = alignDown(indexAddress, ps); |
|
return indexAddress - baseAddress; |
|
} |
|
|
|
// Given an offset previously obtained from calling |
|
// mappingOffset() returns the largest page aligned address of the |
|
|
|
private static long mappingAddress(long address, long mappingOffset) { |
|
return mappingAddress(address, mappingOffset, 0); |
|
} |
|
|
|
// Given an offset previously otained from calling |
|
// mappingOffset(index) returns the largest page aligned address |
|
// of the mapping less than or equal to the address of the buffer |
|
|
|
private static long mappingAddress(long address, long mappingOffset, long index) { |
|
long indexAddress = address + index; |
|
return indexAddress - mappingOffset; |
|
} |
|
|
|
// given a mappingOffset previously otained from calling |
|
// mappingOffset(index) return that offset added to the supplied |
|
|
|
private static long mappingLength(long mappingOffset, long length) { |
|
return length + mappingOffset; |
|
} |
|
|
|
|
|
private static long alignDown(long address, int pageSize) { |
|
|
|
return address & ~(pageSize - 1); |
|
} |
|
} |