comparison src/os/windows/vm/os_windows.cpp @ 389:ee21eaa8ffe1

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
author jmasa
date Thu, 02 Oct 2008 12:01:08 -0700
parents 1ee8caae33af
children 85f1b9537f70 dc16daa0329d
comparison
equal deleted inserted replaced
377:ddfad9496151 389:ee21eaa8ffe1
2591 bool os::can_execute_large_page_memory() { 2591 bool os::can_execute_large_page_memory() {
2592 return true; 2592 return true;
2593 } 2593 }
2594 2594
2595 char* os::reserve_memory_special(size_t bytes) { 2595 char* os::reserve_memory_special(size_t bytes) {
2596 DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; 2596
2597 char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_EXECUTE_READWRITE); 2597 if (UseLargePagesIndividualAllocation) {
2598 return res; 2598 if (TracePageSizes && Verbose) {
2599 tty->print_cr("Reserving large pages individually.");
2600 }
2601 char * p_buf;
2602 // first reserve enough address space in advance since we want to be
2603 // able to break a single contiguous virtual address range into multiple
2604 // large page commits but WS2003 does not allow reserving large page space
2605 // so we just use 4K pages for reserve, this gives us a legal contiguous
2606 // address space. then we will deallocate that reservation, and re alloc
2607 // using large pages
2608 const size_t size_of_reserve = bytes + _large_page_size;
2609 if (bytes > size_of_reserve) {
2610 // Overflowed.
2611 warning("Individually allocated large pages failed, "
2612 "use -XX:-UseLargePagesIndividualAllocation to turn off");
2613 return NULL;
2614 }
2615 p_buf = (char *) VirtualAlloc(NULL,
2616 size_of_reserve, // size of Reserve
2617 MEM_RESERVE,
2618 PAGE_EXECUTE_READWRITE);
2619 // If reservation failed, return NULL
2620 if (p_buf == NULL) return NULL;
2621
2622 release_memory(p_buf, bytes + _large_page_size);
2623 // round up to page boundary. If the size_of_reserve did not
2624 // overflow and the reservation did not fail, this align up
2625 // should not overflow.
2626 p_buf = (char *) align_size_up((size_t)p_buf, _large_page_size);
2627
2628 // now go through and allocate one page at a time until all bytes are
2629 // allocated
2630 size_t bytes_remaining = align_size_up(bytes, _large_page_size);
2631 // An overflow of align_size_up() would have been caught above
2632 // in the calculation of size_of_reserve.
2633 char * next_alloc_addr = p_buf;
2634
2635 #ifdef ASSERT
2636 // Variable for the failure injection
2637 long ran_num = os::random();
2638 size_t fail_after = ran_num % bytes;
2639 #endif
2640
2641 while (bytes_remaining) {
2642 size_t bytes_to_rq = MIN2(bytes_remaining, _large_page_size);
2643 // Note allocate and commit
2644 char * p_new;
2645
2646 #ifdef ASSERT
2647 bool inject_error = LargePagesIndividualAllocationInjectError &&
2648 (bytes_remaining <= fail_after);
2649 #else
2650 const bool inject_error = false;
2651 #endif
2652
2653 if (inject_error) {
2654 p_new = NULL;
2655 } else {
2656 p_new = (char *) VirtualAlloc(next_alloc_addr,
2657 bytes_to_rq,
2658 MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES,
2659 PAGE_EXECUTE_READWRITE);
2660 }
2661
2662 if (p_new == NULL) {
2663 // Free any allocated pages
2664 if (next_alloc_addr > p_buf) {
2665 // Some memory was committed so release it.
2666 size_t bytes_to_release = bytes - bytes_remaining;
2667 release_memory(p_buf, bytes_to_release);
2668 }
2669 #ifdef ASSERT
2670 if (UseLargePagesIndividualAllocation &&
2671 LargePagesIndividualAllocationInjectError) {
2672 if (TracePageSizes && Verbose) {
2673 tty->print_cr("Reserving large pages individually failed.");
2674 }
2675 }
2676 #endif
2677 return NULL;
2678 }
2679 bytes_remaining -= bytes_to_rq;
2680 next_alloc_addr += bytes_to_rq;
2681 }
2682
2683 return p_buf;
2684
2685 } else {
2686 // normal policy just allocate it all at once
2687 DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
2688 char * res = (char *)VirtualAlloc(NULL,
2689 bytes,
2690 flag,
2691 PAGE_EXECUTE_READWRITE);
2692 return res;
2693 }
2599 } 2694 }
2600 2695
2601 bool os::release_memory_special(char* base, size_t bytes) { 2696 bool os::release_memory_special(char* base, size_t bytes) {
2602 return release_memory(base, bytes); 2697 return release_memory(base, bytes);
2603 } 2698 }
2981 3076
2982 intx os::win32::_os_thread_limit = 0; 3077 intx os::win32::_os_thread_limit = 0;
2983 volatile intx os::win32::_os_thread_count = 0; 3078 volatile intx os::win32::_os_thread_count = 0;
2984 3079
2985 bool os::win32::_is_nt = false; 3080 bool os::win32::_is_nt = false;
3081 bool os::win32::_is_windows_2003 = false;
2986 3082
2987 3083
2988 void os::win32::initialize_system_info() { 3084 void os::win32::initialize_system_info() {
2989 SYSTEM_INFO si; 3085 SYSTEM_INFO si;
2990 GetSystemInfo(&si); 3086 GetSystemInfo(&si);
3003 OSVERSIONINFO oi; 3099 OSVERSIONINFO oi;
3004 oi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 3100 oi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
3005 GetVersionEx(&oi); 3101 GetVersionEx(&oi);
3006 switch(oi.dwPlatformId) { 3102 switch(oi.dwPlatformId) {
3007 case VER_PLATFORM_WIN32_WINDOWS: _is_nt = false; break; 3103 case VER_PLATFORM_WIN32_WINDOWS: _is_nt = false; break;
3008 case VER_PLATFORM_WIN32_NT: _is_nt = true; break; 3104 case VER_PLATFORM_WIN32_NT:
3105 _is_nt = true;
3106 {
3107 int os_vers = oi.dwMajorVersion * 1000 + oi.dwMinorVersion;
3108 if (os_vers == 5002) {
3109 _is_windows_2003 = true;
3110 }
3111 }
3112 break;
3009 default: fatal("Unknown platform"); 3113 default: fatal("Unknown platform");
3010 } 3114 }
3011 3115
3012 _default_stack_size = os::current_stack_size(); 3116 _default_stack_size = os::current_stack_size();
3013 assert(_default_stack_size > (size_t) _vm_page_size, "invalid stack size"); 3117 assert(_default_stack_size > (size_t) _vm_page_size, "invalid stack size");
3101 #ifndef PRODUCT 3205 #ifndef PRODUCT
3102 if (is_MP()) { 3206 if (is_MP()) {
3103 NoYieldsInMicrolock = true; 3207 NoYieldsInMicrolock = true;
3104 } 3208 }
3105 #endif 3209 #endif
3210 // This may be overridden later when argument processing is done.
3211 FLAG_SET_ERGO(bool, UseLargePagesIndividualAllocation,
3212 os::win32::is_windows_2003());
3213
3106 // Initialize main_process and main_thread 3214 // Initialize main_process and main_thread
3107 main_process = GetCurrentProcess(); // Remember main_process is a pseudo handle 3215 main_process = GetCurrentProcess(); // Remember main_process is a pseudo handle
3108 if (!DuplicateHandle(main_process, GetCurrentThread(), main_process, 3216 if (!DuplicateHandle(main_process, GetCurrentThread(), main_process,
3109 &main_thread, THREAD_ALL_ACCESS, false, 0)) { 3217 &main_thread, THREAD_ALL_ACCESS, false, 0)) {
3110 fatal("DuplicateHandle failed\n"); 3218 fatal("DuplicateHandle failed\n");
3111 } 3219 }
3112 main_thread_id = (int) GetCurrentThreadId(); 3220 main_thread_id = (int) GetCurrentThreadId();
3113 } 3221 }