Thu, 21 Apr 2011 01:16:20 -0700
Merge
1.1 --- a/src/os/linux/vm/globals_linux.hpp Wed Apr 20 19:19:30 2011 -0700 1.2 +++ b/src/os/linux/vm/globals_linux.hpp Thu Apr 21 01:16:20 2011 -0700 1.3 @@ -29,13 +29,19 @@ 1.4 // Defines Linux specific flags. They are not available on other platforms. 1.5 // 1.6 #define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \ 1.7 - product(bool, UseOprofile, false, \ 1.8 - "enable support for Oprofile profiler") \ 1.9 - \ 1.10 - product(bool, UseLinuxPosixThreadCPUClocks, true, \ 1.11 - "enable fast Linux Posix clocks where available") 1.12 -// NB: The default value of UseLinuxPosixThreadCPUClocks may be 1.13 -// overridden in Arguments::parse_each_vm_init_arg. 1.14 + product(bool, UseOprofile, false, \ 1.15 + "enable support for Oprofile profiler") \ 1.16 + \ 1.17 + product(bool, UseLinuxPosixThreadCPUClocks, true, \ 1.18 + "enable fast Linux Posix clocks where available") \ 1.19 +/* NB: The default value of UseLinuxPosixThreadCPUClocks may be \ 1.20 + overridden in Arguments::parse_each_vm_init_arg. */ \ 1.21 + \ 1.22 + product(bool, UseHugeTLBFS, false, \ 1.23 + "Use MAP_HUGETLB for large pages") \ 1.24 + \ 1.25 + product(bool, UseSHM, false, \ 1.26 + "Use SYSV shared memory for large pages") 1.27 1.28 // 1.29 // Defines Linux-specific default values. The flags are available on all
2.1 --- a/src/os/linux/vm/os_linux.cpp Wed Apr 20 19:19:30 2011 -0700 2.2 +++ b/src/os/linux/vm/os_linux.cpp Thu Apr 21 01:16:20 2011 -0700 2.3 @@ -2465,16 +2465,40 @@ 2.4 return res != (uintptr_t) MAP_FAILED; 2.5 } 2.6 2.7 +// Define MAP_HUGETLB here so we can build HotSpot on old systems. 2.8 +#ifndef MAP_HUGETLB 2.9 +#define MAP_HUGETLB 0x40000 2.10 +#endif 2.11 + 2.12 +// Define MADV_HUGEPAGE here so we can build HotSpot on old systems. 2.13 +#ifndef MADV_HUGEPAGE 2.14 +#define MADV_HUGEPAGE 14 2.15 +#endif 2.16 + 2.17 bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, 2.18 bool exec) { 2.19 + if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) { 2.20 + int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; 2.21 + uintptr_t res = 2.22 + (uintptr_t) ::mmap(addr, size, prot, 2.23 + MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_HUGETLB, 2.24 + -1, 0); 2.25 + return res != (uintptr_t) MAP_FAILED; 2.26 + } 2.27 + 2.28 return commit_memory(addr, size, exec); 2.29 } 2.30 2.31 -void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } 2.32 +void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { 2.33 + if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) { 2.34 + // We don't check the return value: madvise(MADV_HUGEPAGE) may not 2.35 + // be supported or the memory may already be backed by huge pages. 2.36 + ::madvise(addr, bytes, MADV_HUGEPAGE); 2.37 + } 2.38 +} 2.39 2.40 void os::free_memory(char *addr, size_t bytes) { 2.41 - ::mmap(addr, bytes, PROT_READ | PROT_WRITE, 2.42 - MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); 2.43 + ::madvise(addr, bytes, MADV_DONTNEED); 2.44 } 2.45 2.46 void os::numa_make_global(char *addr, size_t bytes) { 2.47 @@ -2818,6 +2842,43 @@ 2.48 return linux_mprotect(addr, size, PROT_READ|PROT_WRITE); 2.49 } 2.50 2.51 +bool os::Linux::hugetlbfs_sanity_check(bool warn, size_t page_size) { 2.52 + bool result = false; 2.53 + void *p = mmap (NULL, page_size, PROT_READ|PROT_WRITE, 2.54 + MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB, 2.55 + -1, 0); 2.56 + 2.57 + if (p != (void *) -1) { 2.58 + // We don't know if this really is a huge page or not. 2.59 + FILE *fp = fopen("/proc/self/maps", "r"); 2.60 + if (fp) { 2.61 + while (!feof(fp)) { 2.62 + char chars[257]; 2.63 + long x = 0; 2.64 + if (fgets(chars, sizeof(chars), fp)) { 2.65 + if (sscanf(chars, "%lx-%*lx", &x) == 1 2.66 + && x == (long)p) { 2.67 + if (strstr (chars, "hugepage")) { 2.68 + result = true; 2.69 + break; 2.70 + } 2.71 + } 2.72 + } 2.73 + } 2.74 + fclose(fp); 2.75 + } 2.76 + munmap (p, page_size); 2.77 + if (result) 2.78 + return true; 2.79 + } 2.80 + 2.81 + if (warn) { 2.82 + warning("HugeTLBFS is not supported by the operating system."); 2.83 + } 2.84 + 2.85 + return result; 2.86 +} 2.87 + 2.88 /* 2.89 * Set the coredump_filter bits to include largepages in core dump (bit 6) 2.90 * 2.91 @@ -2860,7 +2921,16 @@ 2.92 static size_t _large_page_size = 0; 2.93 2.94 bool os::large_page_init() { 2.95 - if (!UseLargePages) return false; 2.96 + if (!UseLargePages) { 2.97 + UseHugeTLBFS = false; 2.98 + UseSHM = false; 2.99 + return false; 2.100 + } 2.101 + 2.102 + if (FLAG_IS_DEFAULT(UseHugeTLBFS) && FLAG_IS_DEFAULT(UseSHM)) { 2.103 + // Our user has not expressed a preference, so we'll try both. 2.104 + UseHugeTLBFS = UseSHM = true; 2.105 + } 2.106 2.107 if (LargePageSizeInBytes) { 2.108 _large_page_size = LargePageSizeInBytes; 2.109 @@ -2905,6 +2975,9 @@ 2.110 } 2.111 } 2.112 2.113 + // print a warning if any large page related flag is specified on command line 2.114 + bool warn_on_failure = !FLAG_IS_DEFAULT(UseHugeTLBFS); 2.115 + 2.116 const size_t default_page_size = (size_t)Linux::page_size(); 2.117 if (_large_page_size > default_page_size) { 2.118 _page_sizes[0] = _large_page_size; 2.119 @@ -2912,6 +2985,14 @@ 2.120 _page_sizes[2] = 0; 2.121 } 2.122 2.123 + UseHugeTLBFS = UseHugeTLBFS && 2.124 + Linux::hugetlbfs_sanity_check(warn_on_failure, _large_page_size); 2.125 + 2.126 + if (UseHugeTLBFS) 2.127 + UseSHM = false; 2.128 + 2.129 + UseLargePages = UseHugeTLBFS || UseSHM; 2.130 + 2.131 set_coredump_filter(); 2.132 2.133 // Large page support is available on 2.6 or newer kernel, some vendors 2.134 @@ -2928,7 +3009,7 @@ 2.135 char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) { 2.136 // "exec" is passed in but not used. Creating the shared image for 2.137 // the code cache doesn't have an SHM_X executable permission to check. 2.138 - assert(UseLargePages, "only for large pages"); 2.139 + assert(UseLargePages && UseSHM, "only for SHM large pages"); 2.140 2.141 key_t key = IPC_PRIVATE; 2.142 char *addr; 2.143 @@ -2995,16 +3076,15 @@ 2.144 return _large_page_size; 2.145 } 2.146 2.147 -// Linux does not support anonymous mmap with large page memory. The only way 2.148 -// to reserve large page memory without file backing is through SysV shared 2.149 -// memory API. The entire memory region is committed and pinned upfront. 2.150 -// Hopefully this will change in the future... 2.151 +// HugeTLBFS allows application to commit large page memory on demand; 2.152 +// with SysV SHM the entire memory region must be allocated as shared 2.153 +// memory. 2.154 bool os::can_commit_large_page_memory() { 2.155 - return false; 2.156 + return UseHugeTLBFS; 2.157 } 2.158 2.159 bool os::can_execute_large_page_memory() { 2.160 - return false; 2.161 + return UseHugeTLBFS; 2.162 } 2.163 2.164 // Reserve memory at an arbitrary address, only if that area is
3.1 --- a/src/os/linux/vm/os_linux.hpp Wed Apr 20 19:19:30 2011 -0700 3.2 +++ b/src/os/linux/vm/os_linux.hpp Thu Apr 21 01:16:20 2011 -0700 3.3 @@ -86,6 +86,9 @@ 3.4 3.5 static void rebuild_cpu_to_node_map(); 3.6 static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; } 3.7 + 3.8 + static bool hugetlbfs_sanity_check(bool warn, size_t page_size); 3.9 + 3.10 public: 3.11 static void init_thread_fpu_state(); 3.12 static int get_fpu_control_word();