Mercurial > hg > graal-compiler
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 |