src/java.base/share/classes/java/nio/MappedByteBuffer.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54904 c1143a0d4e22
child 58679 9c3209ff7550
--- 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;
     }