--- old/src/java.base/share/classes/jdk/internal/misc/Unsafe.java 2018-08-20 11:53:44.610447131 +0100 +++ new/src/java.base/share/classes/jdk/internal/misc/Unsafe.java 2018-08-20 11:53:44.320446267 +0100 @@ -918,6 +918,89 @@ checkPointer(null, address); } + /** + * ensure writeback of a specified virtual memory address range + * from cache to physical memory. all bytes in the address range + * are guaranteed to have been written back to physical memory on + * return from this call i.e. subsequently executed store + * instructions are guaranteed not to be visible before the + * writeback is completed. + * + * @param address + * the lowest byte address that must be guaranteed written + * back to memory. bytes at lower addresses may also be + * written back. + * + * @param length + * the length in bytes of the region starting at address + * that must be guaranteed written back to memory. + * + * @throws RuntimeException if the arguments are invalid + * (Note: after optimization, invalid inputs may + * go undetected, which will lead to unpredictable + * behavior) + * + * @since 12 + */ + + public void writebackMemory(long address, long length) + { + checkWritebackMemory(address, length); + + // perform any required pre-writeback barrier + writebackPreSync0(); + + // write back one cache line at a time + long line = (address & CACHE_LINE_MASK); + long end = address + length; + while (line < end) { + writeback0(line); + line += CACHE_LINE_FLUSH_SIZE; + } + + // perform any required post-writeback barrier + writebackPostSync0(); + } + + /** + * Validate the arguments to writebackMemory + * + * @throws RuntimeException if the arguments are invalid + * (Note: after optimization, invalid inputs may + * go undetected, which will lead to unpredictable + * behavior) + */ + private void checkWritebackMemory(long address, long length) + { + checkNativeAddress(address); + checkSize(length); + } + + /** + * The size of an L1 data cache line which will be a power of two. + */ + private static final long CACHE_LINE_FLUSH_SIZE = (long)theUnsafe.dataCacheLineFlushSize0(); + private static final long CACHE_LINE_MASK = ~(CACHE_LINE_FLUSH_SIZE - 1); + + /** + * primitive operation forcing writeback of a single cache line. + * + * @param address + * the start address of the cache line to be written back + */ + // native used to write back an individual cache line starting at + // the supplied address + @HotSpotIntrinsicCandidate + private native void writeback0(long address); + // native used to serialise writeback operations relative to + // preceding memory writes + @HotSpotIntrinsicCandidate + private native void writebackPreSync0(); + // native used to serialise writeback operations relative to + // following memory writes + @HotSpotIntrinsicCandidate + private native void writebackPostSync0(); + /// random queries /** @@ -1172,7 +1255,6 @@ */ public native int pageSize(); - /// random trusted operations from JNI: /** @@ -3712,6 +3794,7 @@ private native int arrayBaseOffset0(Class arrayClass); private native int arrayIndexScale0(Class arrayClass); private native int addressSize0(); + private native int dataCacheLineFlushSize0(); private native Class defineAnonymousClass0(Class hostClass, byte[] data, Object[] cpPatches); private native int getLoadAverage0(double[] loadavg, int nelems); private native boolean unalignedAccess0();