Thu, 02 Oct 2008 12:01:08 -0700
6660681: Incrementally reserve pages on win server 2003 for better large page affinity
Summary: For windows server 2003 added option to reserve large pages individually.
Reviewed-by: alanb, jcoomes, tonyp, apetrusenko
1.1 --- a/src/os/linux/vm/globals_linux.hpp Wed Oct 01 15:05:06 2008 -0400 1.2 +++ b/src/os/linux/vm/globals_linux.hpp Thu Oct 02 12:01:08 2008 -0700 1.3 @@ -38,5 +38,6 @@ 1.4 // platforms, but they may have different default values on other platforms. 1.5 // 1.6 define_pd_global(bool, UseLargePages, false); 1.7 +define_pd_global(bool, UseLargePagesIndividualAllocation, false); 1.8 define_pd_global(bool, UseOSErrorReporting, false); 1.9 define_pd_global(bool, UseThreadPriorities, true) ;
2.1 --- a/src/os/solaris/vm/globals_solaris.hpp Wed Oct 01 15:05:06 2008 -0400 2.2 +++ b/src/os/solaris/vm/globals_solaris.hpp Thu Oct 02 12:01:08 2008 -0700 2.3 @@ -44,5 +44,6 @@ 2.4 // platforms, but they may have different default values on other platforms. 2.5 // 2.6 define_pd_global(bool, UseLargePages, true); 2.7 +define_pd_global(bool, UseLargePagesIndividualAllocation, false); 2.8 define_pd_global(bool, UseOSErrorReporting, false); 2.9 define_pd_global(bool, UseThreadPriorities, false);
3.1 --- a/src/os/windows/vm/globals_windows.hpp Wed Oct 01 15:05:06 2008 -0400 3.2 +++ b/src/os/windows/vm/globals_windows.hpp Thu Oct 02 12:01:08 2008 -0700 3.3 @@ -37,5 +37,6 @@ 3.4 // platforms, but they may have different default values on other platforms. 3.5 // 3.6 define_pd_global(bool, UseLargePages, false); 3.7 +define_pd_global(bool, UseLargePagesIndividualAllocation, true); 3.8 define_pd_global(bool, UseOSErrorReporting, false); // for now. 3.9 define_pd_global(bool, UseThreadPriorities, true) ;
4.1 --- a/src/os/windows/vm/os_windows.cpp Wed Oct 01 15:05:06 2008 -0400 4.2 +++ b/src/os/windows/vm/os_windows.cpp Thu Oct 02 12:01:08 2008 -0700 4.3 @@ -2593,9 +2593,104 @@ 4.4 } 4.5 4.6 char* os::reserve_memory_special(size_t bytes) { 4.7 - DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; 4.8 - char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_EXECUTE_READWRITE); 4.9 - return res; 4.10 + 4.11 + if (UseLargePagesIndividualAllocation) { 4.12 + if (TracePageSizes && Verbose) { 4.13 + tty->print_cr("Reserving large pages individually."); 4.14 + } 4.15 + char * p_buf; 4.16 + // first reserve enough address space in advance since we want to be 4.17 + // able to break a single contiguous virtual address range into multiple 4.18 + // large page commits but WS2003 does not allow reserving large page space 4.19 + // so we just use 4K pages for reserve, this gives us a legal contiguous 4.20 + // address space. then we will deallocate that reservation, and re alloc 4.21 + // using large pages 4.22 + const size_t size_of_reserve = bytes + _large_page_size; 4.23 + if (bytes > size_of_reserve) { 4.24 + // Overflowed. 4.25 + warning("Individually allocated large pages failed, " 4.26 + "use -XX:-UseLargePagesIndividualAllocation to turn off"); 4.27 + return NULL; 4.28 + } 4.29 + p_buf = (char *) VirtualAlloc(NULL, 4.30 + size_of_reserve, // size of Reserve 4.31 + MEM_RESERVE, 4.32 + PAGE_EXECUTE_READWRITE); 4.33 + // If reservation failed, return NULL 4.34 + if (p_buf == NULL) return NULL; 4.35 + 4.36 + release_memory(p_buf, bytes + _large_page_size); 4.37 + // round up to page boundary. If the size_of_reserve did not 4.38 + // overflow and the reservation did not fail, this align up 4.39 + // should not overflow. 4.40 + p_buf = (char *) align_size_up((size_t)p_buf, _large_page_size); 4.41 + 4.42 + // now go through and allocate one page at a time until all bytes are 4.43 + // allocated 4.44 + size_t bytes_remaining = align_size_up(bytes, _large_page_size); 4.45 + // An overflow of align_size_up() would have been caught above 4.46 + // in the calculation of size_of_reserve. 4.47 + char * next_alloc_addr = p_buf; 4.48 + 4.49 +#ifdef ASSERT 4.50 + // Variable for the failure injection 4.51 + long ran_num = os::random(); 4.52 + size_t fail_after = ran_num % bytes; 4.53 +#endif 4.54 + 4.55 + while (bytes_remaining) { 4.56 + size_t bytes_to_rq = MIN2(bytes_remaining, _large_page_size); 4.57 + // Note allocate and commit 4.58 + char * p_new; 4.59 + 4.60 +#ifdef ASSERT 4.61 + bool inject_error = LargePagesIndividualAllocationInjectError && 4.62 + (bytes_remaining <= fail_after); 4.63 +#else 4.64 + const bool inject_error = false; 4.65 +#endif 4.66 + 4.67 + if (inject_error) { 4.68 + p_new = NULL; 4.69 + } else { 4.70 + p_new = (char *) VirtualAlloc(next_alloc_addr, 4.71 + bytes_to_rq, 4.72 + MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, 4.73 + PAGE_EXECUTE_READWRITE); 4.74 + } 4.75 + 4.76 + if (p_new == NULL) { 4.77 + // Free any allocated pages 4.78 + if (next_alloc_addr > p_buf) { 4.79 + // Some memory was committed so release it. 4.80 + size_t bytes_to_release = bytes - bytes_remaining; 4.81 + release_memory(p_buf, bytes_to_release); 4.82 + } 4.83 +#ifdef ASSERT 4.84 + if (UseLargePagesIndividualAllocation && 4.85 + LargePagesIndividualAllocationInjectError) { 4.86 + if (TracePageSizes && Verbose) { 4.87 + tty->print_cr("Reserving large pages individually failed."); 4.88 + } 4.89 + } 4.90 +#endif 4.91 + return NULL; 4.92 + } 4.93 + bytes_remaining -= bytes_to_rq; 4.94 + next_alloc_addr += bytes_to_rq; 4.95 + } 4.96 + 4.97 + return p_buf; 4.98 + 4.99 + } else { 4.100 + // normal policy just allocate it all at once 4.101 + DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; 4.102 + char * res = (char *)VirtualAlloc(NULL, 4.103 + bytes, 4.104 + flag, 4.105 + PAGE_EXECUTE_READWRITE); 4.106 + return res; 4.107 + } 4.108 } 4.109 4.110 bool os::release_memory_special(char* base, size_t bytes) { 4.111 @@ -2983,6 +3078,7 @@ 4.112 volatile intx os::win32::_os_thread_count = 0; 4.113 4.114 bool os::win32::_is_nt = false; 4.115 +bool os::win32::_is_windows_2003 = false; 4.116 4.117 4.118 void os::win32::initialize_system_info() { 4.119 @@ -3005,7 +3101,15 @@ 4.120 GetVersionEx(&oi); 4.121 switch(oi.dwPlatformId) { 4.122 case VER_PLATFORM_WIN32_WINDOWS: _is_nt = false; break; 4.123 - case VER_PLATFORM_WIN32_NT: _is_nt = true; break; 4.124 + case VER_PLATFORM_WIN32_NT: 4.125 + _is_nt = true; 4.126 + { 4.127 + int os_vers = oi.dwMajorVersion * 1000 + oi.dwMinorVersion; 4.128 + if (os_vers == 5002) { 4.129 + _is_windows_2003 = true; 4.130 + } 4.131 + } 4.132 + break; 4.133 default: fatal("Unknown platform"); 4.134 } 4.135 4.136 @@ -3103,9 +3207,13 @@ 4.137 NoYieldsInMicrolock = true; 4.138 } 4.139 #endif 4.140 + // This may be overridden later when argument processing is done. 4.141 + FLAG_SET_ERGO(bool, UseLargePagesIndividualAllocation, 4.142 + os::win32::is_windows_2003()); 4.143 + 4.144 // Initialize main_process and main_thread 4.145 main_process = GetCurrentProcess(); // Remember main_process is a pseudo handle 4.146 - if (!DuplicateHandle(main_process, GetCurrentThread(), main_process, 4.147 + if (!DuplicateHandle(main_process, GetCurrentThread(), main_process, 4.148 &main_thread, THREAD_ALL_ACCESS, false, 0)) { 4.149 fatal("DuplicateHandle failed\n"); 4.150 }
5.1 --- a/src/os/windows/vm/os_windows.hpp Wed Oct 01 15:05:06 2008 -0400 5.2 +++ b/src/os/windows/vm/os_windows.hpp Thu Oct 02 12:01:08 2008 -0700 5.3 @@ -34,6 +34,7 @@ 5.4 static julong _physical_memory; 5.5 static size_t _default_stack_size; 5.6 static bool _is_nt; 5.7 + static bool _is_windows_2003; 5.8 5.9 public: 5.10 // Windows-specific interface: 5.11 @@ -60,6 +61,9 @@ 5.12 // Tells whether the platform is NT or Windown95 5.13 static bool is_nt() { return _is_nt; } 5.14 5.15 + // Tells whether the platform is Windows 2003 5.16 + static bool is_windows_2003() { return _is_windows_2003; } 5.17 + 5.18 // Returns the byte size of a virtual memory page 5.19 static int vm_page_size() { return _vm_page_size; } 5.20
6.1 --- a/src/share/vm/runtime/globals.hpp Wed Oct 01 15:05:06 2008 -0400 6.2 +++ b/src/share/vm/runtime/globals.hpp Thu Oct 02 12:01:08 2008 -0700 6.3 @@ -330,6 +330,12 @@ 6.4 product_pd(bool, UseLargePages, \ 6.5 "Use large page memory") \ 6.6 \ 6.7 + product_pd(bool, UseLargePagesIndividualAllocation, \ 6.8 + "Allocate large pages individually for better affinity") \ 6.9 + \ 6.10 + develop(bool, LargePagesIndividualAllocationInjectError, false, \ 6.11 + "Fail large pages individual allocation") \ 6.12 + \ 6.13 develop(bool, TracePageSizes, false, \ 6.14 "Trace page size selection and usage.") \ 6.15 \