diff -r 23e3ab980622 -r 9b7b9f16dfd9 src/java.base/share/classes/jdk/internal/misc/Unsafe.java --- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java Tue Aug 20 10:46:23 2019 +0200 +++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java Tue Aug 20 10:11:53 2019 +0100 @@ -921,6 +921,101 @@ 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 memory writeback is not supported + * on the current hardware of if the arguments are invalid. + * (Note: after optimization, invalid inputs may + * go undetected, which will lead to unpredictable + * behavior) + * + * @since 14 + */ + + public void writebackMemory(long address, long length) { + checkWritebackEnabled(); + checkWritebackMemory(address, length); + + // perform any required pre-writeback barrier + writebackPreSync0(); + + // write back one cache line at a time + long line = dataCacheLineAlignDown(address); + long end = address + length; + while (line < end) { + writeback0(line); + line += dataCacheLineFlushSize(); + } + + // 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); + } + + /** + * Validate that the current hardware supports memory writeback. + * (Note: this is a belt and braces check. Clients are + * expected to test whether writeback is enabled by calling + * ({@link isWritebackEnabled #isWritebackEnabled} and avoid + * calling method {@link writeback #writeback} if it is disabled). + * + * + * @throws RuntimeException if memory writeback is not supported + */ + private void checkWritebackEnabled() { + if (!isWritebackEnabled()) { + throw new RuntimeException("writebackMemory not enabled!"); + } + } + + /** + * force writeback of an individual cache line. + * + * @param address + * the start address of the cache line to be written back + */ + @HotSpotIntrinsicCandidate + private native void writeback0(long address); + + /** + * Serialize writeback operations relative to preceding memory writes. + */ + @HotSpotIntrinsicCandidate + private native void writebackPreSync0(); + + /** + * Serialize writeback operations relative to following memory writes. + */ + @HotSpotIntrinsicCandidate + private native void writebackPostSync0(); + /// random queries /** @@ -1175,6 +1270,27 @@ */ public int pageSize() { return PAGE_SIZE; } + /** + * Reports the size in bytes of a data cache line written back by + * the hardware cache line flush operation available to the JVM or + * 0 if data cache line flushing is not enabled. + */ + public int dataCacheLineFlushSize() { return DATA_CACHE_LINE_FLUSH_SIZE; } + + /** + * Rounds down address to a data cache line boundary as + * determined by {@link #dataCacheLineFlushSize} + * @return the rounded down address + */ + public long dataCacheLineAlignDown(long address) { + return (address & ~(DATA_CACHE_LINE_FLUSH_SIZE - 1)); + } + + /** + * Returns true if data cache line writeback + */ + public static boolean isWritebackEnabled() { return DATA_CACHE_LINE_FLUSH_SIZE != 0; } + /// random trusted operations from JNI: /**