mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
6660681: Incrementally reserve pages on win server 2003 for better large page affinity
For windows server 2003 added option to reserve large pages individually. Reviewed-by: alanb, jcoomes, tonyp, apetrusenko
This commit is contained in:
parent
c8006a68d5
commit
6c19542a36
6 changed files with 126 additions and 5 deletions
|
@ -2593,9 +2593,104 @@ bool os::can_execute_large_page_memory() {
|
|||
}
|
||||
|
||||
char* os::reserve_memory_special(size_t bytes) {
|
||||
DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
|
||||
char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_EXECUTE_READWRITE);
|
||||
return res;
|
||||
|
||||
if (UseLargePagesIndividualAllocation) {
|
||||
if (TracePageSizes && Verbose) {
|
||||
tty->print_cr("Reserving large pages individually.");
|
||||
}
|
||||
char * p_buf;
|
||||
// first reserve enough address space in advance since we want to be
|
||||
// able to break a single contiguous virtual address range into multiple
|
||||
// large page commits but WS2003 does not allow reserving large page space
|
||||
// so we just use 4K pages for reserve, this gives us a legal contiguous
|
||||
// address space. then we will deallocate that reservation, and re alloc
|
||||
// using large pages
|
||||
const size_t size_of_reserve = bytes + _large_page_size;
|
||||
if (bytes > size_of_reserve) {
|
||||
// Overflowed.
|
||||
warning("Individually allocated large pages failed, "
|
||||
"use -XX:-UseLargePagesIndividualAllocation to turn off");
|
||||
return NULL;
|
||||
}
|
||||
p_buf = (char *) VirtualAlloc(NULL,
|
||||
size_of_reserve, // size of Reserve
|
||||
MEM_RESERVE,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
// If reservation failed, return NULL
|
||||
if (p_buf == NULL) return NULL;
|
||||
|
||||
release_memory(p_buf, bytes + _large_page_size);
|
||||
// round up to page boundary. If the size_of_reserve did not
|
||||
// overflow and the reservation did not fail, this align up
|
||||
// should not overflow.
|
||||
p_buf = (char *) align_size_up((size_t)p_buf, _large_page_size);
|
||||
|
||||
// now go through and allocate one page at a time until all bytes are
|
||||
// allocated
|
||||
size_t bytes_remaining = align_size_up(bytes, _large_page_size);
|
||||
// An overflow of align_size_up() would have been caught above
|
||||
// in the calculation of size_of_reserve.
|
||||
char * next_alloc_addr = p_buf;
|
||||
|
||||
#ifdef ASSERT
|
||||
// Variable for the failure injection
|
||||
long ran_num = os::random();
|
||||
size_t fail_after = ran_num % bytes;
|
||||
#endif
|
||||
|
||||
while (bytes_remaining) {
|
||||
size_t bytes_to_rq = MIN2(bytes_remaining, _large_page_size);
|
||||
// Note allocate and commit
|
||||
char * p_new;
|
||||
|
||||
#ifdef ASSERT
|
||||
bool inject_error = LargePagesIndividualAllocationInjectError &&
|
||||
(bytes_remaining <= fail_after);
|
||||
#else
|
||||
const bool inject_error = false;
|
||||
#endif
|
||||
|
||||
if (inject_error) {
|
||||
p_new = NULL;
|
||||
} else {
|
||||
p_new = (char *) VirtualAlloc(next_alloc_addr,
|
||||
bytes_to_rq,
|
||||
MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
|
||||
if (p_new == NULL) {
|
||||
// Free any allocated pages
|
||||
if (next_alloc_addr > p_buf) {
|
||||
// Some memory was committed so release it.
|
||||
size_t bytes_to_release = bytes - bytes_remaining;
|
||||
release_memory(p_buf, bytes_to_release);
|
||||
}
|
||||
#ifdef ASSERT
|
||||
if (UseLargePagesIndividualAllocation &&
|
||||
LargePagesIndividualAllocationInjectError) {
|
||||
if (TracePageSizes && Verbose) {
|
||||
tty->print_cr("Reserving large pages individually failed.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
bytes_remaining -= bytes_to_rq;
|
||||
next_alloc_addr += bytes_to_rq;
|
||||
}
|
||||
|
||||
return p_buf;
|
||||
|
||||
} else {
|
||||
// normal policy just allocate it all at once
|
||||
DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
|
||||
char * res = (char *)VirtualAlloc(NULL,
|
||||
bytes,
|
||||
flag,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
bool os::release_memory_special(char* base, size_t bytes) {
|
||||
|
@ -2983,6 +3078,7 @@ size_t os::win32::_default_stack_size = 0;
|
|||
volatile intx os::win32::_os_thread_count = 0;
|
||||
|
||||
bool os::win32::_is_nt = false;
|
||||
bool os::win32::_is_windows_2003 = false;
|
||||
|
||||
|
||||
void os::win32::initialize_system_info() {
|
||||
|
@ -3005,7 +3101,15 @@ void os::win32::initialize_system_info() {
|
|||
GetVersionEx(&oi);
|
||||
switch(oi.dwPlatformId) {
|
||||
case VER_PLATFORM_WIN32_WINDOWS: _is_nt = false; break;
|
||||
case VER_PLATFORM_WIN32_NT: _is_nt = true; break;
|
||||
case VER_PLATFORM_WIN32_NT:
|
||||
_is_nt = true;
|
||||
{
|
||||
int os_vers = oi.dwMajorVersion * 1000 + oi.dwMinorVersion;
|
||||
if (os_vers == 5002) {
|
||||
_is_windows_2003 = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: fatal("Unknown platform");
|
||||
}
|
||||
|
||||
|
@ -3103,9 +3207,13 @@ void os::init(void) {
|
|||
NoYieldsInMicrolock = true;
|
||||
}
|
||||
#endif
|
||||
// This may be overridden later when argument processing is done.
|
||||
FLAG_SET_ERGO(bool, UseLargePagesIndividualAllocation,
|
||||
os::win32::is_windows_2003());
|
||||
|
||||
// Initialize main_process and main_thread
|
||||
main_process = GetCurrentProcess(); // Remember main_process is a pseudo handle
|
||||
if (!DuplicateHandle(main_process, GetCurrentThread(), main_process,
|
||||
if (!DuplicateHandle(main_process, GetCurrentThread(), main_process,
|
||||
&main_thread, THREAD_ALL_ACCESS, false, 0)) {
|
||||
fatal("DuplicateHandle failed\n");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue