8049536: os::commit_memory on Solaris uses aligment_hint as page size
Reviewed-by: stefank, tschatzl
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Sep 15 12:19:31 2014 +0200
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Sep 15 10:57:22 2014 +0200
@@ -2525,29 +2525,30 @@
}
}
+size_t os::Solaris::page_size_for_alignment(size_t alignment) {
+ assert(is_size_aligned(alignment, (size_t) vm_page_size()),
+ err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT,
+ alignment, (size_t) vm_page_size()));
+
+ for (int i = 0; _page_sizes[i] != 0; i++) {
+ if (is_size_aligned(alignment, _page_sizes[i])) {
+ return _page_sizes[i];
+ }
+ }
+
+ return (size_t) vm_page_size();
+}
+
int os::Solaris::commit_memory_impl(char* addr, size_t bytes,
size_t alignment_hint, bool exec) {
int err = Solaris::commit_memory_impl(addr, bytes, exec);
- if (err == 0) {
- if (UseLargePages && (alignment_hint > (size_t)vm_page_size())) {
- // If the large page size has been set and the VM
- // is using large pages, use the large page size
- // if it is smaller than the alignment hint. This is
- // a case where the VM wants to use a larger alignment size
- // for its own reasons but still want to use large pages
- // (which is what matters to setting the mpss range.
- size_t page_size = 0;
- if (large_page_size() < alignment_hint) {
- assert(UseLargePages, "Expected to be here for large page use only");
- page_size = large_page_size();
- } else {
- // If the alignment hint is less than the large page
- // size, the VM wants a particular alignment (thus the hint)
- // for internal reasons. Try to set the mpss range using
- // the alignment_hint.
- page_size = alignment_hint;
- }
- // Since this is a hint, ignore any failures.
+ if (err == 0 && UseLargePages && alignment_hint > 0) {
+ assert(is_size_aligned(bytes, alignment_hint),
+ err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, alignment_hint));
+
+ // The syscall memcntl requires an exact page size (see man memcntl for details).
+ size_t page_size = page_size_for_alignment(alignment_hint);
+ if (page_size > (size_t) vm_page_size()) {
(void)Solaris::setup_large_pages(addr, bytes, page_size);
}
}
@@ -3080,7 +3081,22 @@
}
}
+bool os::Solaris::is_valid_page_size(size_t bytes) {
+ for (int i = 0; _page_sizes[i] != 0; i++) {
+ if (_page_sizes[i] == bytes) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool os::Solaris::setup_large_pages(caddr_t start, size_t bytes, size_t align) {
+ assert(is_valid_page_size(align), err_msg(SIZE_FORMAT " is not a valid page size", align));
+ assert(is_ptr_aligned((void*) start, align),
+ err_msg(PTR_FORMAT " is not aligned to " SIZE_FORMAT, p2i((void*) start), align));
+ assert(is_size_aligned(bytes, align),
+ err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, align));
+
// Signal to OS that we want large pages for addresses
// from addr, addr + bytes
struct memcntl_mha mpss_struct;
--- a/hotspot/src/os/solaris/vm/os_solaris.hpp Mon Sep 15 12:19:31 2014 +0200
+++ b/hotspot/src/os/solaris/vm/os_solaris.hpp Mon Sep 15 10:57:22 2014 +0200
@@ -97,6 +97,8 @@
static meminfo_func_t _meminfo;
// Large Page Support
+ static bool is_valid_page_size(size_t bytes);
+ static size_t page_size_for_alignment(size_t alignment);
static bool setup_large_pages(caddr_t start, size_t bytes, size_t align);
static void init_thread_fpu_state(void);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/memory/LargePages/TestLargePageSizeInBytes.java Mon Sep 15 10:57:22 2014 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test TestLargePageSizeInBytes
+ * @summary Tests that the flag -XX:LargePageSizeInBytes does not cause warnings on Solaris
+ * @bug 8049536
+ * @library /testlibrary
+ * @run driver TestLargePageSizeInBytes
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.ProcessTools;
+
+public class TestLargePageSizeInBytes {
+ private static long M = 1024L * 1024L;
+ private static long G = 1024L * M;
+
+ public static void main(String[] args) throws Exception {
+ if (!Platform.isSolaris()) {
+ // We only use the syscall mencntl on Solaris
+ return;
+ }
+
+ testLargePageSizeInBytes(4 * M);
+ testLargePageSizeInBytes(256 * M);
+ testLargePageSizeInBytes(512 * M);
+ testLargePageSizeInBytes(2 * G);
+ }
+
+ private static void testLargePageSizeInBytes(long size) throws Exception {
+ ProcessBuilder pb =
+ ProcessTools.createJavaProcessBuilder("-XX:+UseLargePages",
+ "-XX:LargePageSizeInBytes=" + size,
+ "-version");
+
+ OutputAnalyzer out = new OutputAnalyzer(pb.start());
+ out.shouldNotContain("Attempt to use MPSS failed.");
+ out.shouldHaveExitValue(0);
+ }
+}