diff --git a/src/share/classes/java/nio/Bits.java b/src/share/classes/java/nio/Bits.java index 4adf3e48066c663306f6d45a9bc2a1bdab48c5e4..fa11b6be785540f23bd3f8e2b0df9a20e8b03513 100644 --- a/src/share/classes/java/nio/Bits.java +++ b/src/share/classes/java/nio/Bits.java @@ -596,6 +596,9 @@ class Bits { // package-private return pageSize; } + static int pageCount(long size) { + return (int)(size + (long)pageSize() - 1L) / pageSize(); + } private static boolean unaligned; private static boolean unalignedKnown = false; diff --git a/src/share/classes/java/nio/MappedByteBuffer.java b/src/share/classes/java/nio/MappedByteBuffer.java index 7e415c67bcaf8bfa22b5e4d65ab556d311455887..4811f41d2e1515deb86f4bfd6409a59fc393e9a4 100644 --- a/src/share/classes/java/nio/MappedByteBuffer.java +++ b/src/share/classes/java/nio/MappedByteBuffer.java @@ -25,6 +25,8 @@ package java.nio; +import sun.misc.Unsafe; + /** * A direct byte buffer whose content is a memory-mapped region of a file. @@ -93,6 +95,22 @@ public abstract class MappedByteBuffer throw new UnsupportedOperationException(); } + // Returns the distance (in bytes) of the buffer from the page aligned address + // of the mapping. Computed each time to avoid storing in every direct buffer. + private long mappingOffset() { + int ps = Bits.pageSize(); + long offset = address % ps; + return (offset >= 0) ? offset : (ps + offset); + } + + private long mappingAddress(long mappingOffset) { + return address - mappingOffset; + } + + private long mappingLength(long mappingOffset) { + return (long)capacity() + mappingOffset; + } + /** * Tells whether or not this buffer's content is resident in physical * memory. @@ -115,7 +133,9 @@ public abstract class MappedByteBuffer checkMapped(); if ((address == 0) || (capacity() == 0)) return true; - return isLoaded0(((DirectByteBuffer)this).address(), capacity()); + long offset = mappingOffset(); + long length = mappingLength(offset); + return isLoaded0(mappingAddress(offset), length, Bits.pageCount(length)); } /** @@ -132,7 +152,20 @@ public abstract class MappedByteBuffer checkMapped(); if ((address == 0) || (capacity() == 0)) return this; - load0(((DirectByteBuffer)this).address(), capacity(), Bits.pageSize()); + long offset = mappingOffset(); + long length = mappingLength(offset); + load0(mappingAddress(offset), length); + + // touch each page + Unsafe unsafe = Unsafe.getUnsafe(); + int ps = Bits.pageSize(); + int count = Bits.pageCount(length); + long a = mappingAddress(offset); + for (int i=0; i #include - JNIEXPORT jboolean JNICALL -Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, - jlong address, jlong len) +Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, jlong address, + jlong len, jint numPages) { jboolean loaded = JNI_TRUE; - jint pageSize = sysconf(_SC_PAGESIZE); - jint numPages = (len + pageSize - 1) / pageSize; int result = 0; int i = 0; void *a = (void *) jlong_to_ptr(address); @@ -55,9 +52,9 @@ Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, } result = mincore(a, (size_t)len, vec); - if (result != 0) { - free(vec); + if (result == -1) { JNU_ThrowIOExceptionWithLastError(env, "mincore failed"); + free(vec); return JNI_FALSE; } @@ -72,23 +69,15 @@ Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, } -JNIEXPORT jint JNICALL +JNIEXPORT void JNICALL Java_java_nio_MappedByteBuffer_load0(JNIEnv *env, jobject obj, jlong address, - jlong len, jint pageSize) + jlong len) { - int pageIncrement = pageSize / sizeof(int); - int numPages = (len + pageSize - 1) / pageSize; - int *ptr = (int *)jlong_to_ptr(address); - int i = 0; - int j = 0; - int result = madvise((caddr_t)ptr, len, MADV_WILLNEED); - - /* touch every page */ - for (i=0; i JNIEXPORT jboolean JNICALL -Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, - jlong address, jlong len) +Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, jlong address, + jlong len, jint numPages) { jboolean loaded = JNI_FALSE; /* Information not available? @@ -43,22 +43,11 @@ Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, return loaded; } -JNIEXPORT jint JNICALL +JNIEXPORT void JNICALL Java_java_nio_MappedByteBuffer_load0(JNIEnv *env, jobject obj, jlong address, - jlong len, jint pageSize) + jlong len) { - int *ptr = (int *) jlong_to_ptr(address); - int pageIncrement = pageSize / sizeof(int); - jlong numPages = (len + pageSize - 1) / pageSize; - int i = 0; - int j = 0; - - /* touch every page */ - for (i=0; i() { + public Void call() { + mbb.get((int)TRUNCATED_FILE_SIZE + 1); + mbb.put((int)TRUNCATED_FILE_SIZE + 2, (byte)123); + return null; + } + }); + // Test 2: load buffer into memory + execute(new Callable() { + public Void call() throws IOException { + mbb.load(); + return null; + } + }); + } + fc.close(); + } + + // Runs the given task in its own thread. If operating correcting the + // the thread will terminate with an InternalError as the mapped buffer + // is inaccessible. + static void execute(final Callable c) { + Runnable r = new Runnable() { + public void run() { + try { + Object ignore = c.call(); + } catch (Exception ignore) { + } + } + }; + Thread t = new Thread(r); + t.start(); + try { t.join(); } catch (InterruptedException ignore) { } + } +}