--- a/src/java.base/share/classes/java/nio/MappedByteBuffer.java Thu Oct 17 20:27:44 2019 +0100
+++ b/src/java.base/share/classes/java/nio/MappedByteBuffer.java Thu Oct 17 20:53:35 2019 +0100
@@ -78,18 +78,33 @@
// operations if valid; null if the buffer is not mapped.
private final FileDescriptor fd;
+ // A flag true if this buffer is mapped against non-volatile
+ // memory using one of the extended FileChannel.MapMode modes,
+ // MapMode.READ_ONLY_SYNC or MapMode.READ_WRITE_SYNC and false if
+ // it is mapped using any of the other modes. This flag only
+ // determines the behavior of force operations.
+ private final boolean isSync;
+
// This should only be invoked by the DirectByteBuffer constructors
//
MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
- FileDescriptor fd)
- {
+ FileDescriptor fd, boolean isSync) {
super(mark, pos, lim, cap);
this.fd = fd;
+ this.isSync = isSync;
+ }
+
+ MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
+ boolean isSync) {
+ super(mark, pos, lim, cap);
+ this.fd = null;
+ this.isSync = isSync;
}
MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private
super(mark, pos, lim, cap);
this.fd = null;
+ this.isSync = false;
}
// Returns the distance (in bytes) of the buffer start from the
@@ -147,6 +162,23 @@
}
/**
+ * Tells whether this buffer was mapped against a non-volatile
+ * memory device by passing one of the sync map modes {@link
+ * jdk.nio.mapmode.ExtendedMapMode#READ_ONLY_SYNC
+ * ExtendedMapModeMapMode#READ_ONLY_SYNC} or {@link
+ * jdk.nio.mapmode.ExtendedMapMode#READ_ONLY_SYNC
+ * ExtendedMapMode#READ_WRITE_SYNC} in the call to {@link
+ * java.nio.channels.FileChannel#map FileChannel.map} or was
+ * mapped by passing one of the other map modes.
+ *
+ * @return true if the file was mapped using one of the sync map
+ * modes, otherwise false.
+ */
+ private boolean isSync() {
+ return isSync;
+ }
+
+ /**
* Tells whether or not this buffer's content is resident in physical
* memory.
*
@@ -168,6 +200,10 @@
if (fd == null) {
return true;
}
+ // a sync mapped buffer is always loaded
+ if (isSync()) {
+ return true;
+ }
if ((address == 0) || (capacity() == 0))
return true;
long offset = mappingOffset();
@@ -192,6 +228,10 @@
if (fd == null) {
return this;
}
+ // no need to load a sync mapped buffer
+ if (isSync()) {
+ return this;
+ }
if ((address == 0) || (capacity() == 0))
return this;
long offset = mappingOffset();
@@ -235,8 +275,11 @@
* is made.
*
* <p> If this buffer was not mapped in read/write mode ({@link
- * java.nio.channels.FileChannel.MapMode#READ_WRITE}) then invoking this
- * method has no effect. </p>
+ * java.nio.channels.FileChannel.MapMode#READ_WRITE}) then
+ * invoking this method may have no effect. In particular, the
+ * method has no effect for buffers mapped in read-only or private
+ * mapping modes. This method may or may not have an effect for
+ * implementation-specific mapping modes. </p>
*
* @return This buffer
*/
@@ -244,6 +287,9 @@
if (fd == null) {
return this;
}
+ if (isSync) {
+ return force(0, limit());
+ }
if ((address != 0) && (capacity() != 0)) {
long offset = mappingOffset();
force0(fd, mappingAddress(offset), mappingLength(offset));
@@ -271,16 +317,19 @@
*
* <p> If this buffer was not mapped in read/write mode ({@link
* java.nio.channels.FileChannel.MapMode#READ_WRITE}) then
- * invoking this method has no effect. </p>
+ * invoking this method may have no effect. In particular, the
+ * method has no effect for buffers mapped in read-only or private
+ * mapping modes. This method may or may not have an effect for
+ * implementation-specific mapping modes. </p>
*
- * @param index
- * The index of the first byte in the buffer region that is
- * to be written back to storage; must be non-negative
- * and less than limit()
+ * @param index
+ * The index of the first byte in the buffer region that is
+ * to be written back to storage; must be non-negative
+ * and less than limit()
*
- * @param length
- * The length of the region in bytes; must be non-negative
- * and no larger than limit() - index
+ * @param length
+ * The length of the region in bytes; must be non-negative
+ * and no larger than limit() - index
*
* @throws IndexOutOfBoundsException
* if the preconditions on the index and length do not
@@ -297,8 +346,14 @@
if ((address != 0) && (limit() != 0)) {
// check inputs
Objects.checkFromIndexSize(index, length, limit());
- long offset = mappingOffset(index);
- force0(fd, mappingAddress(offset, index), mappingLength(offset, length));
+ if (isSync) {
+ // simply force writeback of associated cache lines
+ Unsafe.getUnsafe().writebackMemory(address + index, length);
+ } else {
+ // force writeback via file descriptor
+ long offset = mappingOffset(index);
+ force0(fd, mappingAddress(offset, index), mappingLength(offset, length));
+ }
}
return this;
}