2830 size_t page_size = UseLargePages ? _large_page_size : os::vm_allocation_granularity();
2831 size_t chunk_size = UseNUMAInterleaving ? NUMAInterleaveGranularity : page_size;
2832
2833 // first reserve enough address space in advance since we want to be
2834 // able to break a single contiguous virtual address range into multiple
2835 // large page commits but WS2003 does not allow reserving large page space
2836 // so we just use 4K pages for reserve, this gives us a legal contiguous
2837 // address space. then we will deallocate that reservation, and re alloc
2838 // using large pages
2839 const size_t size_of_reserve = bytes + chunk_size;
2840 if (bytes > size_of_reserve) {
2841 // Overflowed.
2842 return NULL;
2843 }
2844 p_buf = (char *) VirtualAlloc(addr,
2845 size_of_reserve, // size of Reserve
2846 MEM_RESERVE,
2847 PAGE_READWRITE);
2848 // If reservation failed, return NULL
2849 if (p_buf == NULL) return NULL;
2850 MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC);
2851 os::release_memory(p_buf, bytes + chunk_size);
2852
2853 // we still need to round up to a page boundary (in case we are using large pages)
2854 // but not to a chunk boundary (in case InterleavingGranularity doesn't align with page size)
2855 // instead we handle this in the bytes_to_rq computation below
2856 p_buf = (char *) align_size_up((size_t)p_buf, page_size);
2857
2858 // now go through and allocate one chunk at a time until all bytes are
2859 // allocated
2860 size_t bytes_remaining = bytes;
2861 // An overflow of align_size_up() would have been caught above
2862 // in the calculation of size_of_reserve.
2863 char * next_alloc_addr = p_buf;
2864 HANDLE hProc = GetCurrentProcess();
2865
2866 #ifdef ASSERT
2867 // Variable for the failure injection
2868 long ran_num = os::random();
2869 size_t fail_after = ran_num % bytes;
2870 #endif
2896 assert(numa_node_list_holder.get_count() > 0, "Multiple NUMA nodes expected");
2897 DWORD node = numa_node_list_holder.get_node_list_entry(count % numa_node_list_holder.get_count());
2898 p_new = (char *)os::Kernel32Dll::VirtualAllocExNuma(hProc,
2899 next_alloc_addr,
2900 bytes_to_rq,
2901 flags,
2902 prot,
2903 node);
2904 }
2905 }
2906
2907 if (p_new == NULL) {
2908 // Free any allocated pages
2909 if (next_alloc_addr > p_buf) {
2910 // Some memory was committed so release it.
2911 size_t bytes_to_release = bytes - bytes_remaining;
2912 // NMT has yet to record any individual blocks, so it
2913 // need to create a dummy 'reserve' record to match
2914 // the release.
2915 MemTracker::record_virtual_memory_reserve((address)p_buf,
2916 bytes_to_release, CALLER_PC);
2917 os::release_memory(p_buf, bytes_to_release);
2918 }
2919 #ifdef ASSERT
2920 if (should_inject_error) {
2921 if (TracePageSizes && Verbose) {
2922 tty->print_cr("Reserving pages individually failed.");
2923 }
2924 }
2925 #endif
2926 return NULL;
2927 }
2928
2929 bytes_remaining -= bytes_to_rq;
2930 next_alloc_addr += bytes_to_rq;
2931 count++;
2932 }
2933 // Although the memory is allocated individually, it is returned as one.
2934 // NMT records it as one block.
2935 address pc = CALLER_PC;
2936 MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, pc);
2937 if ((flags & MEM_COMMIT) != 0) {
2938 MemTracker::record_virtual_memory_commit((address)p_buf, bytes, pc);
2939 }
2940
2941 // made it this far, success
2942 return p_buf;
2943 }
2944
2945
2946
2947 void os::large_page_init() {
2948 if (!UseLargePages) return;
2949
2950 // print a warning if any large page related flag is specified on command line
2951 bool warn_on_failure = !FLAG_IS_DEFAULT(UseLargePages) ||
2952 !FLAG_IS_DEFAULT(LargePageSizeInBytes);
2953 bool success = false;
2954
2955 # define WARN(msg) if (warn_on_failure) { warning(msg); }
2956 if (resolve_functions_for_large_page_init()) {
2957 if (request_lock_memory_privilege()) {
2958 size_t s = os::Kernel32Dll::GetLargePageMinimum();
3109 if (p_buf == NULL) {
3110 // give an appropriate warning message
3111 if (UseNUMAInterleaving) {
3112 warning("NUMA large page allocation failed, UseLargePages flag ignored");
3113 }
3114 if (UseLargePagesIndividualAllocation) {
3115 warning("Individually allocated large pages failed, "
3116 "use -XX:-UseLargePagesIndividualAllocation to turn off");
3117 }
3118 return NULL;
3119 }
3120
3121 return p_buf;
3122
3123 } else {
3124 // normal policy just allocate it all at once
3125 DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
3126 char * res = (char *)VirtualAlloc(NULL, bytes, flag, prot);
3127 if (res != NULL) {
3128 address pc = CALLER_PC;
3129 MemTracker::record_virtual_memory_reserve((address)res, bytes, pc);
3130 MemTracker::record_virtual_memory_commit((address)res, bytes, pc);
3131 }
3132
3133 return res;
3134 }
3135 }
3136
3137 bool os::release_memory_special(char* base, size_t bytes) {
3138 assert(base != NULL, "Sanity check");
3139 // Memory allocated via reserve_memory_special() is committed
3140 MemTracker::record_virtual_memory_uncommit((address)base, bytes);
3141 return release_memory(base, bytes);
3142 }
3143
3144 void os::print_statistics() {
3145 }
3146
3147 bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) {
3148 if (bytes == 0) {
3149 // Don't bother the OS with noops.
3150 return true;
3151 }
3152 assert((size_t) addr % os::vm_page_size() == 0, "commit on page boundaries");
3153 assert(bytes % os::vm_page_size() == 0, "commit in page-sized chunks");
3154 // Don't attempt to print anything if the OS call fails. We're
3155 // probably low on resources, so the print itself may cause crashes.
3156
3157 // unless we have NUMAInterleaving enabled, the range of a commit
3158 // is always within a reserve covered by a single VirtualAlloc
3159 // in that case we can just do a single commit for the requested size
3160 if (!UseNUMAInterleaving) {
|
2830 size_t page_size = UseLargePages ? _large_page_size : os::vm_allocation_granularity();
2831 size_t chunk_size = UseNUMAInterleaving ? NUMAInterleaveGranularity : page_size;
2832
2833 // first reserve enough address space in advance since we want to be
2834 // able to break a single contiguous virtual address range into multiple
2835 // large page commits but WS2003 does not allow reserving large page space
2836 // so we just use 4K pages for reserve, this gives us a legal contiguous
2837 // address space. then we will deallocate that reservation, and re alloc
2838 // using large pages
2839 const size_t size_of_reserve = bytes + chunk_size;
2840 if (bytes > size_of_reserve) {
2841 // Overflowed.
2842 return NULL;
2843 }
2844 p_buf = (char *) VirtualAlloc(addr,
2845 size_of_reserve, // size of Reserve
2846 MEM_RESERVE,
2847 PAGE_READWRITE);
2848 // If reservation failed, return NULL
2849 if (p_buf == NULL) return NULL;
2850 MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, mtNone, CALLER_PC);
2851 os::release_memory(p_buf, bytes + chunk_size);
2852
2853 // we still need to round up to a page boundary (in case we are using large pages)
2854 // but not to a chunk boundary (in case InterleavingGranularity doesn't align with page size)
2855 // instead we handle this in the bytes_to_rq computation below
2856 p_buf = (char *) align_size_up((size_t)p_buf, page_size);
2857
2858 // now go through and allocate one chunk at a time until all bytes are
2859 // allocated
2860 size_t bytes_remaining = bytes;
2861 // An overflow of align_size_up() would have been caught above
2862 // in the calculation of size_of_reserve.
2863 char * next_alloc_addr = p_buf;
2864 HANDLE hProc = GetCurrentProcess();
2865
2866 #ifdef ASSERT
2867 // Variable for the failure injection
2868 long ran_num = os::random();
2869 size_t fail_after = ran_num % bytes;
2870 #endif
2896 assert(numa_node_list_holder.get_count() > 0, "Multiple NUMA nodes expected");
2897 DWORD node = numa_node_list_holder.get_node_list_entry(count % numa_node_list_holder.get_count());
2898 p_new = (char *)os::Kernel32Dll::VirtualAllocExNuma(hProc,
2899 next_alloc_addr,
2900 bytes_to_rq,
2901 flags,
2902 prot,
2903 node);
2904 }
2905 }
2906
2907 if (p_new == NULL) {
2908 // Free any allocated pages
2909 if (next_alloc_addr > p_buf) {
2910 // Some memory was committed so release it.
2911 size_t bytes_to_release = bytes - bytes_remaining;
2912 // NMT has yet to record any individual blocks, so it
2913 // need to create a dummy 'reserve' record to match
2914 // the release.
2915 MemTracker::record_virtual_memory_reserve((address)p_buf,
2916 bytes_to_release, mtNone, CALLER_PC);
2917 os::release_memory(p_buf, bytes_to_release);
2918 }
2919 #ifdef ASSERT
2920 if (should_inject_error) {
2921 if (TracePageSizes && Verbose) {
2922 tty->print_cr("Reserving pages individually failed.");
2923 }
2924 }
2925 #endif
2926 return NULL;
2927 }
2928
2929 bytes_remaining -= bytes_to_rq;
2930 next_alloc_addr += bytes_to_rq;
2931 count++;
2932 }
2933 // Although the memory is allocated individually, it is returned as one.
2934 // NMT records it as one block.
2935 address pc = CALLER_PC;
2936 if ((flags & MEM_COMMIT) != 0) {
2937 MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, mtNone, pc);
2938 } else {
2939 MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, mtNone, pc);
2940 }
2941
2942 // made it this far, success
2943 return p_buf;
2944 }
2945
2946
2947
2948 void os::large_page_init() {
2949 if (!UseLargePages) return;
2950
2951 // print a warning if any large page related flag is specified on command line
2952 bool warn_on_failure = !FLAG_IS_DEFAULT(UseLargePages) ||
2953 !FLAG_IS_DEFAULT(LargePageSizeInBytes);
2954 bool success = false;
2955
2956 # define WARN(msg) if (warn_on_failure) { warning(msg); }
2957 if (resolve_functions_for_large_page_init()) {
2958 if (request_lock_memory_privilege()) {
2959 size_t s = os::Kernel32Dll::GetLargePageMinimum();
3110 if (p_buf == NULL) {
3111 // give an appropriate warning message
3112 if (UseNUMAInterleaving) {
3113 warning("NUMA large page allocation failed, UseLargePages flag ignored");
3114 }
3115 if (UseLargePagesIndividualAllocation) {
3116 warning("Individually allocated large pages failed, "
3117 "use -XX:-UseLargePagesIndividualAllocation to turn off");
3118 }
3119 return NULL;
3120 }
3121
3122 return p_buf;
3123
3124 } else {
3125 // normal policy just allocate it all at once
3126 DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
3127 char * res = (char *)VirtualAlloc(NULL, bytes, flag, prot);
3128 if (res != NULL) {
3129 address pc = CALLER_PC;
3130 MemTracker::record_virtual_memory_reserve_and_commit((address)res, bytes, mtNone, pc);
3131 }
3132
3133 return res;
3134 }
3135 }
3136
3137 bool os::release_memory_special(char* base, size_t bytes) {
3138 assert(base != NULL, "Sanity check");
3139 return release_memory(base, bytes);
3140 }
3141
3142 void os::print_statistics() {
3143 }
3144
3145 bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) {
3146 if (bytes == 0) {
3147 // Don't bother the OS with noops.
3148 return true;
3149 }
3150 assert((size_t) addr % os::vm_page_size() == 0, "commit on page boundaries");
3151 assert(bytes % os::vm_page_size() == 0, "commit in page-sized chunks");
3152 // Don't attempt to print anything if the OS call fails. We're
3153 // probably low on resources, so the print itself may cause crashes.
3154
3155 // unless we have NUMAInterleaving enabled, the range of a commit
3156 // is always within a reserve covered by a single VirtualAlloc
3157 // in that case we can just do a single commit for the requested size
3158 if (!UseNUMAInterleaving) {
|