comparison src/os/windows/vm/os_windows.cpp @ 10969:a837fa3d3f86

8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint Summary: Detect mmap() commit failures in Linux and Solaris os::commit_memory() impls and call vm_exit_out_of_memory(). Add os::commit_memory_or_exit(). Also tidy up some NMT accounting and some mmap() return value checking. Reviewed-by: zgu, stefank, dholmes, dsamersoff
author dcubed
date Thu, 13 Jun 2013 11:16:38 -0700
parents f2110083203d
children 1f4355cee9a2
comparison
equal deleted inserted replaced
10405:f2110083203d 10969:a837fa3d3f86
2522 address addr = (address) exceptionRecord->ExceptionInformation[1]; 2522 address addr = (address) exceptionRecord->ExceptionInformation[1];
2523 if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() ) { 2523 if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() ) {
2524 addr = (address)((uintptr_t)addr & 2524 addr = (address)((uintptr_t)addr &
2525 (~((uintptr_t)os::vm_page_size() - (uintptr_t)1))); 2525 (~((uintptr_t)os::vm_page_size() - (uintptr_t)1)));
2526 os::commit_memory((char *)addr, thread->stack_base() - addr, 2526 os::commit_memory((char *)addr, thread->stack_base() - addr,
2527 false ); 2527 !ExecMem);
2528 return EXCEPTION_CONTINUE_EXECUTION; 2528 return EXCEPTION_CONTINUE_EXECUTION;
2529 } 2529 }
2530 else 2530 else
2531 #endif 2531 #endif
2532 { 2532 {
3170 } 3170 }
3171 3171
3172 void os::print_statistics() { 3172 void os::print_statistics() {
3173 } 3173 }
3174 3174
3175 static void warn_fail_commit_memory(char* addr, size_t bytes, bool exec) {
3176 int err = os::get_last_error();
3177 char buf[256];
3178 size_t buf_len = os::lasterror(buf, sizeof(buf));
3179 warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
3180 ", %d) failed; error='%s' (DOS error/errno=%d)", addr, bytes,
3181 exec, buf_len != 0 ? buf : "<no_error_string>", err);
3182 }
3183
3175 bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) { 3184 bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) {
3176 if (bytes == 0) { 3185 if (bytes == 0) {
3177 // Don't bother the OS with noops. 3186 // Don't bother the OS with noops.
3178 return true; 3187 return true;
3179 } 3188 }
3184 3193
3185 // unless we have NUMAInterleaving enabled, the range of a commit 3194 // unless we have NUMAInterleaving enabled, the range of a commit
3186 // is always within a reserve covered by a single VirtualAlloc 3195 // is always within a reserve covered by a single VirtualAlloc
3187 // in that case we can just do a single commit for the requested size 3196 // in that case we can just do a single commit for the requested size
3188 if (!UseNUMAInterleaving) { 3197 if (!UseNUMAInterleaving) {
3189 if (VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE) == NULL) return false; 3198 if (VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE) == NULL) {
3199 NOT_PRODUCT(warn_fail_commit_memory(addr, bytes, exec);)
3200 return false;
3201 }
3190 if (exec) { 3202 if (exec) {
3191 DWORD oldprot; 3203 DWORD oldprot;
3192 // Windows doc says to use VirtualProtect to get execute permissions 3204 // Windows doc says to use VirtualProtect to get execute permissions
3193 if (!VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &oldprot)) return false; 3205 if (!VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &oldprot)) {
3206 NOT_PRODUCT(warn_fail_commit_memory(addr, bytes, exec);)
3207 return false;
3208 }
3194 } 3209 }
3195 return true; 3210 return true;
3196 } else { 3211 } else {
3197 3212
3198 // when NUMAInterleaving is enabled, the commit might cover a range that 3213 // when NUMAInterleaving is enabled, the commit might cover a range that
3203 char * next_alloc_addr = addr; 3218 char * next_alloc_addr = addr;
3204 while (bytes_remaining > 0) { 3219 while (bytes_remaining > 0) {
3205 MEMORY_BASIC_INFORMATION alloc_info; 3220 MEMORY_BASIC_INFORMATION alloc_info;
3206 VirtualQuery(next_alloc_addr, &alloc_info, sizeof(alloc_info)); 3221 VirtualQuery(next_alloc_addr, &alloc_info, sizeof(alloc_info));
3207 size_t bytes_to_rq = MIN2(bytes_remaining, (size_t)alloc_info.RegionSize); 3222 size_t bytes_to_rq = MIN2(bytes_remaining, (size_t)alloc_info.RegionSize);
3208 if (VirtualAlloc(next_alloc_addr, bytes_to_rq, MEM_COMMIT, PAGE_READWRITE) == NULL) 3223 if (VirtualAlloc(next_alloc_addr, bytes_to_rq, MEM_COMMIT,
3224 PAGE_READWRITE) == NULL) {
3225 NOT_PRODUCT(warn_fail_commit_memory(next_alloc_addr, bytes_to_rq,
3226 exec);)
3209 return false; 3227 return false;
3228 }
3210 if (exec) { 3229 if (exec) {
3211 DWORD oldprot; 3230 DWORD oldprot;
3212 if (!VirtualProtect(next_alloc_addr, bytes_to_rq, PAGE_EXECUTE_READWRITE, &oldprot)) 3231 if (!VirtualProtect(next_alloc_addr, bytes_to_rq,
3232 PAGE_EXECUTE_READWRITE, &oldprot)) {
3233 NOT_PRODUCT(warn_fail_commit_memory(next_alloc_addr, bytes_to_rq,
3234 exec);)
3213 return false; 3235 return false;
3236 }
3214 } 3237 }
3215 bytes_remaining -= bytes_to_rq; 3238 bytes_remaining -= bytes_to_rq;
3216 next_alloc_addr += bytes_to_rq; 3239 next_alloc_addr += bytes_to_rq;
3217 } 3240 }
3218 } 3241 }
3220 return true; 3243 return true;
3221 } 3244 }
3222 3245
3223 bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint, 3246 bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint,
3224 bool exec) { 3247 bool exec) {
3225 return commit_memory(addr, size, exec); 3248 // alignment_hint is ignored on this OS
3249 return pd_commit_memory(addr, size, exec);
3250 }
3251
3252 void os::pd_commit_memory_or_exit(char* addr, size_t size, bool exec,
3253 const char* mesg) {
3254 assert(mesg != NULL, "mesg must be specified");
3255 if (!pd_commit_memory(addr, size, exec)) {
3256 warn_fail_commit_memory(addr, size, exec);
3257 vm_exit_out_of_memory(size, OOM_MMAP_ERROR, mesg);
3258 }
3259 }
3260
3261 void os::pd_commit_memory_or_exit(char* addr, size_t size,
3262 size_t alignment_hint, bool exec,
3263 const char* mesg) {
3264 // alignment_hint is ignored on this OS
3265 pd_commit_memory_or_exit(addr, size, exec, mesg);
3226 } 3266 }
3227 3267
3228 bool os::pd_uncommit_memory(char* addr, size_t bytes) { 3268 bool os::pd_uncommit_memory(char* addr, size_t bytes) {
3229 if (bytes == 0) { 3269 if (bytes == 0) {
3230 // Don't bother the OS with noops. 3270 // Don't bother the OS with noops.
3238 bool os::pd_release_memory(char* addr, size_t bytes) { 3278 bool os::pd_release_memory(char* addr, size_t bytes) {
3239 return VirtualFree(addr, 0, MEM_RELEASE) != 0; 3279 return VirtualFree(addr, 0, MEM_RELEASE) != 0;
3240 } 3280 }
3241 3281
3242 bool os::pd_create_stack_guard_pages(char* addr, size_t size) { 3282 bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
3243 return os::commit_memory(addr, size); 3283 return os::commit_memory(addr, size, !ExecMem);
3244 } 3284 }
3245 3285
3246 bool os::remove_stack_guard_pages(char* addr, size_t size) { 3286 bool os::remove_stack_guard_pages(char* addr, size_t size) {
3247 return os::uncommit_memory(addr, size); 3287 return os::uncommit_memory(addr, size);
3248 } 3288 }
3262 3302
3263 DWORD old_status; 3303 DWORD old_status;
3264 3304
3265 // Strange enough, but on Win32 one can change protection only for committed 3305 // Strange enough, but on Win32 one can change protection only for committed
3266 // memory, not a big deal anyway, as bytes less or equal than 64K 3306 // memory, not a big deal anyway, as bytes less or equal than 64K
3267 if (!is_committed && !commit_memory(addr, bytes, prot == MEM_PROT_RWX)) { 3307 if (!is_committed) {
3268 fatal("cannot commit protection page"); 3308 commit_memory_or_exit(addr, bytes, prot == MEM_PROT_RWX,
3309 "cannot commit protection page");
3269 } 3310 }
3270 // One cannot use os::guard_memory() here, as on Win32 guard page 3311 // One cannot use os::guard_memory() here, as on Win32 guard page
3271 // have different (one-shot) semantics, from MSDN on PAGE_GUARD: 3312 // have different (one-shot) semantics, from MSDN on PAGE_GUARD:
3272 // 3313 //
3273 // Pages in the region become guard pages. Any attempt to access a guard page 3314 // Pages in the region become guard pages. Any attempt to access a guard page