comparison src/os/windows/vm/os_windows.cpp @ 4137:04b9a2566eec

Merge with hsx23/hotspot.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sat, 17 Dec 2011 21:40:27 +0100
parents 285d51520d4c 436b4a3231bf
children acf7d88327fa
comparison
equal deleted inserted replaced
3737:9dc19b7d89a3 4137:04b9a2566eec
707 } else { 707 } else {
708 return proc_count; 708 return proc_count;
709 } 709 }
710 } 710 }
711 711
712 void os::set_native_thread_name(const char *name) {
713 // Not yet implemented.
714 return;
715 }
716
712 bool os::distribute_processes(uint length, uint* distribution) { 717 bool os::distribute_processes(uint length, uint* distribution) {
713 // Not yet implemented. 718 // Not yet implemented.
714 return false; 719 return false;
715 } 720 }
716 721
1643 } 1648 }
1644 } 1649 }
1645 st->print(" Build %d", osvi.dwBuildNumber); 1650 st->print(" Build %d", osvi.dwBuildNumber);
1646 st->print(" %s", osvi.szCSDVersion); // service pack 1651 st->print(" %s", osvi.szCSDVersion); // service pack
1647 st->cr(); 1652 st->cr();
1653 }
1654
1655 void os::pd_print_cpu_info(outputStream* st) {
1656 // Nothing to do for now.
1648 } 1657 }
1649 1658
1650 void os::print_memory_info(outputStream* st) { 1659 void os::print_memory_info(outputStream* st) {
1651 st->print("Memory:"); 1660 st->print("Memory:");
1652 st->print(" %dk page", os::vm_page_size()>>10); 1661 st->print(" %dk page", os::vm_page_size()>>10);
2607 #endif 2616 #endif
2608 2617
2609 static HANDLE _hProcess; 2618 static HANDLE _hProcess;
2610 static HANDLE _hToken; 2619 static HANDLE _hToken;
2611 2620
2621 // Container for NUMA node list info
2622 class NUMANodeListHolder {
2623 private:
2624 int *_numa_used_node_list; // allocated below
2625 int _numa_used_node_count;
2626
2627 void free_node_list() {
2628 if (_numa_used_node_list != NULL) {
2629 FREE_C_HEAP_ARRAY(int, _numa_used_node_list);
2630 }
2631 }
2632
2633 public:
2634 NUMANodeListHolder() {
2635 _numa_used_node_count = 0;
2636 _numa_used_node_list = NULL;
2637 // do rest of initialization in build routine (after function pointers are set up)
2638 }
2639
2640 ~NUMANodeListHolder() {
2641 free_node_list();
2642 }
2643
2644 bool build() {
2645 DWORD_PTR proc_aff_mask;
2646 DWORD_PTR sys_aff_mask;
2647 if (!GetProcessAffinityMask(GetCurrentProcess(), &proc_aff_mask, &sys_aff_mask)) return false;
2648 ULONG highest_node_number;
2649 if (!os::Kernel32Dll::GetNumaHighestNodeNumber(&highest_node_number)) return false;
2650 free_node_list();
2651 _numa_used_node_list = NEW_C_HEAP_ARRAY(int, highest_node_number + 1);
2652 for (unsigned int i = 0; i <= highest_node_number; i++) {
2653 ULONGLONG proc_mask_numa_node;
2654 if (!os::Kernel32Dll::GetNumaNodeProcessorMask(i, &proc_mask_numa_node)) return false;
2655 if ((proc_aff_mask & proc_mask_numa_node)!=0) {
2656 _numa_used_node_list[_numa_used_node_count++] = i;
2657 }
2658 }
2659 return (_numa_used_node_count > 1);
2660 }
2661
2662 int get_count() {return _numa_used_node_count;}
2663 int get_node_list_entry(int n) {
2664 // for indexes out of range, returns -1
2665 return (n < _numa_used_node_count ? _numa_used_node_list[n] : -1);
2666 }
2667
2668 } numa_node_list_holder;
2669
2670
2671
2612 static size_t _large_page_size = 0; 2672 static size_t _large_page_size = 0;
2613 2673
2614 static bool resolve_functions_for_large_page_init() { 2674 static bool resolve_functions_for_large_page_init() {
2615 return os::Kernel32Dll::GetLargePageMinimumAvailable() && 2675 return os::Kernel32Dll::GetLargePageMinimumAvailable() &&
2616 os::Advapi32Dll::AdvapiAvailable(); 2676 os::Advapi32Dll::AdvapiAvailable();
2645 if (_hProcess) CloseHandle(_hProcess); 2705 if (_hProcess) CloseHandle(_hProcess);
2646 _hProcess = NULL; 2706 _hProcess = NULL;
2647 if (_hToken) CloseHandle(_hToken); 2707 if (_hToken) CloseHandle(_hToken);
2648 _hToken = NULL; 2708 _hToken = NULL;
2649 } 2709 }
2710
2711 static bool numa_interleaving_init() {
2712 bool success = false;
2713 bool use_numa_interleaving_specified = !FLAG_IS_DEFAULT(UseNUMAInterleaving);
2714
2715 // print a warning if UseNUMAInterleaving flag is specified on command line
2716 bool warn_on_failure = use_numa_interleaving_specified;
2717 # define WARN(msg) if (warn_on_failure) { warning(msg); }
2718
2719 // NUMAInterleaveGranularity cannot be less than vm_allocation_granularity (or _large_page_size if using large pages)
2720 size_t min_interleave_granularity = UseLargePages ? _large_page_size : os::vm_allocation_granularity();
2721 NUMAInterleaveGranularity = align_size_up(NUMAInterleaveGranularity, min_interleave_granularity);
2722
2723 if (os::Kernel32Dll::NumaCallsAvailable()) {
2724 if (numa_node_list_holder.build()) {
2725 if (PrintMiscellaneous && Verbose) {
2726 tty->print("NUMA UsedNodeCount=%d, namely ", numa_node_list_holder.get_count());
2727 for (int i = 0; i < numa_node_list_holder.get_count(); i++) {
2728 tty->print("%d ", numa_node_list_holder.get_node_list_entry(i));
2729 }
2730 tty->print("\n");
2731 }
2732 success = true;
2733 } else {
2734 WARN("Process does not cover multiple NUMA nodes.");
2735 }
2736 } else {
2737 WARN("NUMA Interleaving is not supported by the operating system.");
2738 }
2739 if (!success) {
2740 if (use_numa_interleaving_specified) WARN("...Ignoring UseNUMAInterleaving flag.");
2741 }
2742 return success;
2743 #undef WARN
2744 }
2745
2746 // this routine is used whenever we need to reserve a contiguous VA range
2747 // but we need to make separate VirtualAlloc calls for each piece of the range
2748 // Reasons for doing this:
2749 // * UseLargePagesIndividualAllocation was set (normally only needed on WS2003 but possible to be set otherwise)
2750 // * UseNUMAInterleaving requires a separate node for each piece
2751 static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, DWORD prot,
2752 bool should_inject_error=false) {
2753 char * p_buf;
2754 // note: at setup time we guaranteed that NUMAInterleaveGranularity was aligned up to a page size
2755 size_t page_size = UseLargePages ? _large_page_size : os::vm_allocation_granularity();
2756 size_t chunk_size = UseNUMAInterleaving ? NUMAInterleaveGranularity : page_size;
2757
2758 // first reserve enough address space in advance since we want to be
2759 // able to break a single contiguous virtual address range into multiple
2760 // large page commits but WS2003 does not allow reserving large page space
2761 // so we just use 4K pages for reserve, this gives us a legal contiguous
2762 // address space. then we will deallocate that reservation, and re alloc
2763 // using large pages
2764 const size_t size_of_reserve = bytes + chunk_size;
2765 if (bytes > size_of_reserve) {
2766 // Overflowed.
2767 return NULL;
2768 }
2769 p_buf = (char *) VirtualAlloc(addr,
2770 size_of_reserve, // size of Reserve
2771 MEM_RESERVE,
2772 PAGE_READWRITE);
2773 // If reservation failed, return NULL
2774 if (p_buf == NULL) return NULL;
2775
2776 os::release_memory(p_buf, bytes + chunk_size);
2777
2778 // we still need to round up to a page boundary (in case we are using large pages)
2779 // but not to a chunk boundary (in case InterleavingGranularity doesn't align with page size)
2780 // instead we handle this in the bytes_to_rq computation below
2781 p_buf = (char *) align_size_up((size_t)p_buf, page_size);
2782
2783 // now go through and allocate one chunk at a time until all bytes are
2784 // allocated
2785 size_t bytes_remaining = bytes;
2786 // An overflow of align_size_up() would have been caught above
2787 // in the calculation of size_of_reserve.
2788 char * next_alloc_addr = p_buf;
2789 HANDLE hProc = GetCurrentProcess();
2790
2791 #ifdef ASSERT
2792 // Variable for the failure injection
2793 long ran_num = os::random();
2794 size_t fail_after = ran_num % bytes;
2795 #endif
2796
2797 int count=0;
2798 while (bytes_remaining) {
2799 // select bytes_to_rq to get to the next chunk_size boundary
2800
2801 size_t bytes_to_rq = MIN2(bytes_remaining, chunk_size - ((size_t)next_alloc_addr % chunk_size));
2802 // Note allocate and commit
2803 char * p_new;
2804
2805 #ifdef ASSERT
2806 bool inject_error_now = should_inject_error && (bytes_remaining <= fail_after);
2807 #else
2808 const bool inject_error_now = false;
2809 #endif
2810
2811 if (inject_error_now) {
2812 p_new = NULL;
2813 } else {
2814 if (!UseNUMAInterleaving) {
2815 p_new = (char *) VirtualAlloc(next_alloc_addr,
2816 bytes_to_rq,
2817 flags,
2818 prot);
2819 } else {
2820 // get the next node to use from the used_node_list
2821 assert(numa_node_list_holder.get_count() > 0, "Multiple NUMA nodes expected");
2822 DWORD node = numa_node_list_holder.get_node_list_entry(count % numa_node_list_holder.get_count());
2823 p_new = (char *)os::Kernel32Dll::VirtualAllocExNuma(hProc,
2824 next_alloc_addr,
2825 bytes_to_rq,
2826 flags,
2827 prot,
2828 node);
2829 }
2830 }
2831
2832 if (p_new == NULL) {
2833 // Free any allocated pages
2834 if (next_alloc_addr > p_buf) {
2835 // Some memory was committed so release it.
2836 size_t bytes_to_release = bytes - bytes_remaining;
2837 os::release_memory(p_buf, bytes_to_release);
2838 }
2839 #ifdef ASSERT
2840 if (should_inject_error) {
2841 if (TracePageSizes && Verbose) {
2842 tty->print_cr("Reserving pages individually failed.");
2843 }
2844 }
2845 #endif
2846 return NULL;
2847 }
2848 bytes_remaining -= bytes_to_rq;
2849 next_alloc_addr += bytes_to_rq;
2850 count++;
2851 }
2852 // made it this far, success
2853 return p_buf;
2854 }
2855
2856
2650 2857
2651 void os::large_page_init() { 2858 void os::large_page_init() {
2652 if (!UseLargePages) return; 2859 if (!UseLargePages) return;
2653 2860
2654 // print a warning if any large page related flag is specified on command line 2861 // print a warning if any large page related flag is specified on command line
2715 2922
2716 char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { 2923 char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
2717 assert((size_t)addr % os::vm_allocation_granularity() == 0, 2924 assert((size_t)addr % os::vm_allocation_granularity() == 0,
2718 "reserve alignment"); 2925 "reserve alignment");
2719 assert(bytes % os::vm_allocation_granularity() == 0, "reserve block size"); 2926 assert(bytes % os::vm_allocation_granularity() == 0, "reserve block size");
2720 char* res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE); 2927 char* res;
2928 // note that if UseLargePages is on, all the areas that require interleaving
2929 // will go thru reserve_memory_special rather than thru here.
2930 bool use_individual = (UseNUMAInterleaving && !UseLargePages);
2931 if (!use_individual) {
2932 res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE);
2933 } else {
2934 elapsedTimer reserveTimer;
2935 if( Verbose && PrintMiscellaneous ) reserveTimer.start();
2936 // in numa interleaving, we have to allocate pages individually
2937 // (well really chunks of NUMAInterleaveGranularity size)
2938 res = allocate_pages_individually(bytes, addr, MEM_RESERVE, PAGE_READWRITE);
2939 if (res == NULL) {
2940 warning("NUMA page allocation failed");
2941 }
2942 if( Verbose && PrintMiscellaneous ) {
2943 reserveTimer.stop();
2944 tty->print_cr("reserve_memory of %Ix bytes took %ld ms (%ld ticks)", bytes,
2945 reserveTimer.milliseconds(), reserveTimer.ticks());
2946 }
2947 }
2721 assert(res == NULL || addr == NULL || addr == res, 2948 assert(res == NULL || addr == NULL || addr == res,
2722 "Unexpected address from reserve."); 2949 "Unexpected address from reserve.");
2950
2723 return res; 2951 return res;
2724 } 2952 }
2725 2953
2726 // Reserve memory at an arbitrary address, only if that area is 2954 // Reserve memory at an arbitrary address, only if that area is
2727 // available (and not reserved for something else). 2955 // available (and not reserved for something else).
2747 } 2975 }
2748 2976
2749 char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) { 2977 char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) {
2750 2978
2751 const DWORD prot = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 2979 const DWORD prot = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
2752 2980 const DWORD flags = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
2753 if (UseLargePagesIndividualAllocation) { 2981
2982 // with large pages, there are two cases where we need to use Individual Allocation
2983 // 1) the UseLargePagesIndividualAllocation flag is set (set by default on WS2003)
2984 // 2) NUMA Interleaving is enabled, in which case we use a different node for each page
2985 if (UseLargePagesIndividualAllocation || UseNUMAInterleaving) {
2754 if (TracePageSizes && Verbose) { 2986 if (TracePageSizes && Verbose) {
2755 tty->print_cr("Reserving large pages individually."); 2987 tty->print_cr("Reserving large pages individually.");
2756 } 2988 }
2757 char * p_buf; 2989 char * p_buf = allocate_pages_individually(bytes, addr, flags, prot, LargePagesIndividualAllocationInjectError);
2758 // first reserve enough address space in advance since we want to be 2990 if (p_buf == NULL) {
2759 // able to break a single contiguous virtual address range into multiple 2991 // give an appropriate warning message
2760 // large page commits but WS2003 does not allow reserving large page space 2992 if (UseNUMAInterleaving) {
2761 // so we just use 4K pages for reserve, this gives us a legal contiguous 2993 warning("NUMA large page allocation failed, UseLargePages flag ignored");
2762 // address space. then we will deallocate that reservation, and re alloc 2994 }
2763 // using large pages 2995 if (UseLargePagesIndividualAllocation) {
2764 const size_t size_of_reserve = bytes + _large_page_size; 2996 warning("Individually allocated large pages failed, "
2765 if (bytes > size_of_reserve) { 2997 "use -XX:-UseLargePagesIndividualAllocation to turn off");
2766 // Overflowed. 2998 }
2767 warning("Individually allocated large pages failed, "
2768 "use -XX:-UseLargePagesIndividualAllocation to turn off");
2769 return NULL; 2999 return NULL;
2770 }
2771 p_buf = (char *) VirtualAlloc(addr,
2772 size_of_reserve, // size of Reserve
2773 MEM_RESERVE,
2774 PAGE_READWRITE);
2775 // If reservation failed, return NULL
2776 if (p_buf == NULL) return NULL;
2777
2778 release_memory(p_buf, bytes + _large_page_size);
2779 // round up to page boundary. If the size_of_reserve did not
2780 // overflow and the reservation did not fail, this align up
2781 // should not overflow.
2782 p_buf = (char *) align_size_up((size_t)p_buf, _large_page_size);
2783
2784 // now go through and allocate one page at a time until all bytes are
2785 // allocated
2786 size_t bytes_remaining = align_size_up(bytes, _large_page_size);
2787 // An overflow of align_size_up() would have been caught above
2788 // in the calculation of size_of_reserve.
2789 char * next_alloc_addr = p_buf;
2790
2791 #ifdef ASSERT
2792 // Variable for the failure injection
2793 long ran_num = os::random();
2794 size_t fail_after = ran_num % bytes;
2795 #endif
2796
2797 while (bytes_remaining) {
2798 size_t bytes_to_rq = MIN2(bytes_remaining, _large_page_size);
2799 // Note allocate and commit
2800 char * p_new;
2801
2802 #ifdef ASSERT
2803 bool inject_error = LargePagesIndividualAllocationInjectError &&
2804 (bytes_remaining <= fail_after);
2805 #else
2806 const bool inject_error = false;
2807 #endif
2808
2809 if (inject_error) {
2810 p_new = NULL;
2811 } else {
2812 p_new = (char *) VirtualAlloc(next_alloc_addr,
2813 bytes_to_rq,
2814 MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES,
2815 prot);
2816 }
2817
2818 if (p_new == NULL) {
2819 // Free any allocated pages
2820 if (next_alloc_addr > p_buf) {
2821 // Some memory was committed so release it.
2822 size_t bytes_to_release = bytes - bytes_remaining;
2823 release_memory(p_buf, bytes_to_release);
2824 }
2825 #ifdef ASSERT
2826 if (UseLargePagesIndividualAllocation &&
2827 LargePagesIndividualAllocationInjectError) {
2828 if (TracePageSizes && Verbose) {
2829 tty->print_cr("Reserving large pages individually failed.");
2830 }
2831 }
2832 #endif
2833 return NULL;
2834 }
2835 bytes_remaining -= bytes_to_rq;
2836 next_alloc_addr += bytes_to_rq;
2837 } 3000 }
2838 3001
2839 return p_buf; 3002 return p_buf;
2840 3003
2841 } else { 3004 } else {
2860 } 3023 }
2861 assert((size_t) addr % os::vm_page_size() == 0, "commit on page boundaries"); 3024 assert((size_t) addr % os::vm_page_size() == 0, "commit on page boundaries");
2862 assert(bytes % os::vm_page_size() == 0, "commit in page-sized chunks"); 3025 assert(bytes % os::vm_page_size() == 0, "commit in page-sized chunks");
2863 // Don't attempt to print anything if the OS call fails. We're 3026 // Don't attempt to print anything if the OS call fails. We're
2864 // probably low on resources, so the print itself may cause crashes. 3027 // probably low on resources, so the print itself may cause crashes.
2865 bool result = VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE) != 0; 3028
2866 if (result != NULL && exec) { 3029 // unless we have NUMAInterleaving enabled, the range of a commit
2867 DWORD oldprot; 3030 // is always within a reserve covered by a single VirtualAlloc
2868 // Windows doc says to use VirtualProtect to get execute permissions 3031 // in that case we can just do a single commit for the requested size
2869 return VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &oldprot) != 0; 3032 if (!UseNUMAInterleaving) {
3033 if (VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE) == NULL) return false;
3034 if (exec) {
3035 DWORD oldprot;
3036 // Windows doc says to use VirtualProtect to get execute permissions
3037 if (!VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &oldprot)) return false;
3038 }
3039 return true;
2870 } else { 3040 } else {
2871 return result; 3041
2872 } 3042 // when NUMAInterleaving is enabled, the commit might cover a range that
3043 // came from multiple VirtualAlloc reserves (using allocate_pages_individually).
3044 // VirtualQuery can help us determine that. The RegionSize that VirtualQuery
3045 // returns represents the number of bytes that can be committed in one step.
3046 size_t bytes_remaining = bytes;
3047 char * next_alloc_addr = addr;
3048 while (bytes_remaining > 0) {
3049 MEMORY_BASIC_INFORMATION alloc_info;
3050 VirtualQuery(next_alloc_addr, &alloc_info, sizeof(alloc_info));
3051 size_t bytes_to_rq = MIN2(bytes_remaining, (size_t)alloc_info.RegionSize);
3052 if (VirtualAlloc(next_alloc_addr, bytes_to_rq, MEM_COMMIT, PAGE_READWRITE) == NULL)
3053 return false;
3054 if (exec) {
3055 DWORD oldprot;
3056 if (!VirtualProtect(next_alloc_addr, bytes_to_rq, PAGE_EXECUTE_READWRITE, &oldprot))
3057 return false;
3058 }
3059 bytes_remaining -= bytes_to_rq;
3060 next_alloc_addr += bytes_to_rq;
3061 }
3062 }
3063 // if we made it this far, return true
3064 return true;
2873 } 3065 }
2874 3066
2875 bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, 3067 bool os::commit_memory(char* addr, size_t size, size_t alignment_hint,
2876 bool exec) { 3068 bool exec) {
2877 return commit_memory(addr, size, exec); 3069 return commit_memory(addr, size, exec);
2941 void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } 3133 void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { }
2942 void os::free_memory(char *addr, size_t bytes) { } 3134 void os::free_memory(char *addr, size_t bytes) { }
2943 void os::numa_make_global(char *addr, size_t bytes) { } 3135 void os::numa_make_global(char *addr, size_t bytes) { }
2944 void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { } 3136 void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { }
2945 bool os::numa_topology_changed() { return false; } 3137 bool os::numa_topology_changed() { return false; }
2946 size_t os::numa_get_groups_num() { return 1; } 3138 size_t os::numa_get_groups_num() { return MAX2(numa_node_list_holder.get_count(), 1); }
2947 int os::numa_get_group_id() { return 0; } 3139 int os::numa_get_group_id() { return 0; }
2948 size_t os::numa_get_leaf_groups(int *ids, size_t size) { 3140 size_t os::numa_get_leaf_groups(int *ids, size_t size) {
2949 if (size > 0) { 3141 if (numa_node_list_holder.get_count() == 0 && size > 0) {
3142 // Provide an answer for UMA systems
2950 ids[0] = 0; 3143 ids[0] = 0;
2951 return 1; 3144 return 1;
2952 } 3145 } else {
2953 return 0; 3146 // check for size bigger than actual groups_num
3147 size = MIN2(size, numa_get_groups_num());
3148 for (int i = 0; i < (int)size; i++) {
3149 ids[i] = numa_node_list_holder.get_node_list_entry(i);
3150 }
3151 return size;
3152 }
2954 } 3153 }
2955 3154
2956 bool os::get_page_info(char *start, page_info* info) { 3155 bool os::get_page_info(char *start, page_info* info) {
2957 return false; 3156 return false;
2958 } 3157 }
3473 3672
3474 #ifndef PRODUCT 3673 #ifndef PRODUCT
3475 if(Verbose && PrintMiscellaneous) 3674 if(Verbose && PrintMiscellaneous)
3476 tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); 3675 tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page);
3477 #endif 3676 #endif
3478 } 3677 }
3479 3678
3480 os::large_page_init(); 3679 os::large_page_init();
3481 3680
3482 // Setup Windows Exceptions 3681 // Setup Windows Exceptions
3483 3682
3577 3776
3578 // initialize thread priority policy 3777 // initialize thread priority policy
3579 prio_init(); 3778 prio_init();
3580 3779
3581 if (UseNUMA && !ForceNUMA) { 3780 if (UseNUMA && !ForceNUMA) {
3582 UseNUMA = false; // Currently unsupported. 3781 UseNUMA = false; // We don't fully support this yet
3782 }
3783
3784 if (UseNUMAInterleaving) {
3785 // first check whether this Windows OS supports VirtualAllocExNuma, if not ignore this flag
3786 bool success = numa_interleaving_init();
3787 if (!success) UseNUMAInterleaving = false;
3583 } 3788 }
3584 3789
3585 return JNI_OK; 3790 return JNI_OK;
3586 } 3791 }
3587 3792
4751 } 4956 }
4752 4957
4753 4958
4754 // Kernel32 API 4959 // Kernel32 API
4755 typedef SIZE_T (WINAPI* GetLargePageMinimum_Fn)(void); 4960 typedef SIZE_T (WINAPI* GetLargePageMinimum_Fn)(void);
4961 typedef LPVOID (WINAPI *VirtualAllocExNuma_Fn) (HANDLE, LPVOID, SIZE_T, DWORD, DWORD, DWORD);
4962 typedef BOOL (WINAPI *GetNumaHighestNodeNumber_Fn) (PULONG);
4963 typedef BOOL (WINAPI *GetNumaNodeProcessorMask_Fn) (UCHAR, PULONGLONG);
4964
4756 GetLargePageMinimum_Fn os::Kernel32Dll::_GetLargePageMinimum = NULL; 4965 GetLargePageMinimum_Fn os::Kernel32Dll::_GetLargePageMinimum = NULL;
4966 VirtualAllocExNuma_Fn os::Kernel32Dll::_VirtualAllocExNuma = NULL;
4967 GetNumaHighestNodeNumber_Fn os::Kernel32Dll::_GetNumaHighestNodeNumber = NULL;
4968 GetNumaNodeProcessorMask_Fn os::Kernel32Dll::_GetNumaNodeProcessorMask = NULL;
4757 BOOL os::Kernel32Dll::initialized = FALSE; 4969 BOOL os::Kernel32Dll::initialized = FALSE;
4758 SIZE_T os::Kernel32Dll::GetLargePageMinimum() { 4970 SIZE_T os::Kernel32Dll::GetLargePageMinimum() {
4759 assert(initialized && _GetLargePageMinimum != NULL, 4971 assert(initialized && _GetLargePageMinimum != NULL,
4760 "GetLargePageMinimumAvailable() not yet called"); 4972 "GetLargePageMinimumAvailable() not yet called");
4761 return _GetLargePageMinimum(); 4973 return _GetLargePageMinimum();
4766 initialize(); 4978 initialize();
4767 } 4979 }
4768 return _GetLargePageMinimum != NULL; 4980 return _GetLargePageMinimum != NULL;
4769 } 4981 }
4770 4982
4771 4983 BOOL os::Kernel32Dll::NumaCallsAvailable() {
4772 #ifndef JDK6_OR_EARLIER 4984 if (!initialized) {
4773 4985 initialize();
4774 void os::Kernel32Dll::initialize() { 4986 }
4987 return _VirtualAllocExNuma != NULL;
4988 }
4989
4990 LPVOID os::Kernel32Dll::VirtualAllocExNuma(HANDLE hProc, LPVOID addr, SIZE_T bytes, DWORD flags, DWORD prot, DWORD node) {
4991 assert(initialized && _VirtualAllocExNuma != NULL,
4992 "NUMACallsAvailable() not yet called");
4993
4994 return _VirtualAllocExNuma(hProc, addr, bytes, flags, prot, node);
4995 }
4996
4997 BOOL os::Kernel32Dll::GetNumaHighestNodeNumber(PULONG ptr_highest_node_number) {
4998 assert(initialized && _GetNumaHighestNodeNumber != NULL,
4999 "NUMACallsAvailable() not yet called");
5000
5001 return _GetNumaHighestNodeNumber(ptr_highest_node_number);
5002 }
5003
5004 BOOL os::Kernel32Dll::GetNumaNodeProcessorMask(UCHAR node, PULONGLONG proc_mask) {
5005 assert(initialized && _GetNumaNodeProcessorMask != NULL,
5006 "NUMACallsAvailable() not yet called");
5007
5008 return _GetNumaNodeProcessorMask(node, proc_mask);
5009 }
5010
5011
5012 void os::Kernel32Dll::initializeCommon() {
4775 if (!initialized) { 5013 if (!initialized) {
4776 HMODULE handle = ::GetModuleHandle("Kernel32.dll"); 5014 HMODULE handle = ::GetModuleHandle("Kernel32.dll");
4777 assert(handle != NULL, "Just check"); 5015 assert(handle != NULL, "Just check");
4778 _GetLargePageMinimum = (GetLargePageMinimum_Fn)::GetProcAddress(handle, "GetLargePageMinimum"); 5016 _GetLargePageMinimum = (GetLargePageMinimum_Fn)::GetProcAddress(handle, "GetLargePageMinimum");
5017 _VirtualAllocExNuma = (VirtualAllocExNuma_Fn)::GetProcAddress(handle, "VirtualAllocExNuma");
5018 _GetNumaHighestNodeNumber = (GetNumaHighestNodeNumber_Fn)::GetProcAddress(handle, "GetNumaHighestNodeNumber");
5019 _GetNumaNodeProcessorMask = (GetNumaNodeProcessorMask_Fn)::GetProcAddress(handle, "GetNumaNodeProcessorMask");
4779 initialized = TRUE; 5020 initialized = TRUE;
4780 } 5021 }
5022 }
5023
5024
5025
5026 #ifndef JDK6_OR_EARLIER
5027
5028 void os::Kernel32Dll::initialize() {
5029 initializeCommon();
4781 } 5030 }
4782 5031
4783 5032
4784 // Kernel32 API 5033 // Kernel32 API
4785 inline BOOL os::Kernel32Dll::SwitchToThread() { 5034 inline BOOL os::Kernel32Dll::SwitchToThread() {
4880 CreateToolhelp32Snapshot_Fn os::Kernel32Dll::_CreateToolhelp32Snapshot = NULL; 5129 CreateToolhelp32Snapshot_Fn os::Kernel32Dll::_CreateToolhelp32Snapshot = NULL;
4881 Module32First_Fn os::Kernel32Dll::_Module32First = NULL; 5130 Module32First_Fn os::Kernel32Dll::_Module32First = NULL;
4882 Module32Next_Fn os::Kernel32Dll::_Module32Next = NULL; 5131 Module32Next_Fn os::Kernel32Dll::_Module32Next = NULL;
4883 GetNativeSystemInfo_Fn os::Kernel32Dll::_GetNativeSystemInfo = NULL; 5132 GetNativeSystemInfo_Fn os::Kernel32Dll::_GetNativeSystemInfo = NULL;
4884 5133
5134
4885 void os::Kernel32Dll::initialize() { 5135 void os::Kernel32Dll::initialize() {
4886 if (!initialized) { 5136 if (!initialized) {
4887 HMODULE handle = ::GetModuleHandle("Kernel32.dll"); 5137 HMODULE handle = ::GetModuleHandle("Kernel32.dll");
4888 assert(handle != NULL, "Just check"); 5138 assert(handle != NULL, "Just check");
4889 5139
4890 _SwitchToThread = (SwitchToThread_Fn)::GetProcAddress(handle, "SwitchToThread"); 5140 _SwitchToThread = (SwitchToThread_Fn)::GetProcAddress(handle, "SwitchToThread");
4891 _GetLargePageMinimum = (GetLargePageMinimum_Fn)::GetProcAddress(handle, "GetLargePageMinimum");
4892 _CreateToolhelp32Snapshot = (CreateToolhelp32Snapshot_Fn) 5141 _CreateToolhelp32Snapshot = (CreateToolhelp32Snapshot_Fn)
4893 ::GetProcAddress(handle, "CreateToolhelp32Snapshot"); 5142 ::GetProcAddress(handle, "CreateToolhelp32Snapshot");
4894 _Module32First = (Module32First_Fn)::GetProcAddress(handle, "Module32First"); 5143 _Module32First = (Module32First_Fn)::GetProcAddress(handle, "Module32First");
4895 _Module32Next = (Module32Next_Fn)::GetProcAddress(handle, "Module32Next"); 5144 _Module32Next = (Module32Next_Fn)::GetProcAddress(handle, "Module32Next");
4896 _GetNativeSystemInfo = (GetNativeSystemInfo_Fn)::GetProcAddress(handle, "GetNativeSystemInfo"); 5145 _GetNativeSystemInfo = (GetNativeSystemInfo_Fn)::GetProcAddress(handle, "GetNativeSystemInfo");
5146 initializeCommon(); // resolve the functions that always need resolving
4897 5147
4898 initialized = TRUE; 5148 initialized = TRUE;
4899 } 5149 }
4900 } 5150 }
4901 5151
4956 assert(initialized && _GetNativeSystemInfo != NULL, 5206 assert(initialized && _GetNativeSystemInfo != NULL,
4957 "GetNativeSystemInfoAvailable() not yet called"); 5207 "GetNativeSystemInfoAvailable() not yet called");
4958 5208
4959 _GetNativeSystemInfo(lpSystemInfo); 5209 _GetNativeSystemInfo(lpSystemInfo);
4960 } 5210 }
5211
5212
4961 5213
4962 // PSAPI API 5214 // PSAPI API
4963 5215
4964 5216
4965 typedef BOOL (WINAPI *EnumProcessModules_Fn)(HANDLE, HMODULE *, DWORD, LPDWORD); 5217 typedef BOOL (WINAPI *EnumProcessModules_Fn)(HANDLE, HMODULE *, DWORD, LPDWORD);
5072 _AdjustTokenPrivileges = (AdjustTokenPrivileges_Fn)::GetProcAddress(handle, 5324 _AdjustTokenPrivileges = (AdjustTokenPrivileges_Fn)::GetProcAddress(handle,
5073 "AdjustTokenPrivileges"); 5325 "AdjustTokenPrivileges");
5074 _OpenProcessToken = (OpenProcessToken_Fn)::GetProcAddress(handle, 5326 _OpenProcessToken = (OpenProcessToken_Fn)::GetProcAddress(handle,
5075 "OpenProcessToken"); 5327 "OpenProcessToken");
5076 _LookupPrivilegeValue = (LookupPrivilegeValue_Fn)::GetProcAddress(handle, 5328 _LookupPrivilegeValue = (LookupPrivilegeValue_Fn)::GetProcAddress(handle,
5077 "LookupPrivilegeValue"); 5329 "LookupPrivilegeValueA");
5078 } 5330 }
5079 initialized = TRUE; 5331 initialized = TRUE;
5080 } 5332 }
5081 } 5333 }
5082 5334