3397 // Don't bother the OS with noops.
3398 return true;
3399 }
3400 assert((size_t) addr % os::vm_page_size() == 0, "uncommit on page boundaries");
3401 assert(bytes % os::vm_page_size() == 0, "uncommit in page-sized chunks");
3402 return (VirtualFree(addr, bytes, MEM_DECOMMIT) != 0);
3403 }
3404
3405 bool os::pd_release_memory(char* addr, size_t bytes) {
3406 return VirtualFree(addr, 0, MEM_RELEASE) != 0;
3407 }
3408
3409 bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
3410 return os::commit_memory(addr, size, !ExecMem);
3411 }
3412
3413 bool os::remove_stack_guard_pages(char* addr, size_t size) {
3414 return os::uncommit_memory(addr, size);
3415 }
3416
3417 // Set protections specified
3418 bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
3419 bool is_committed) {
3420 unsigned int p = 0;
3421 switch (prot) {
3422 case MEM_PROT_NONE: p = PAGE_NOACCESS; break;
3423 case MEM_PROT_READ: p = PAGE_READONLY; break;
3424 case MEM_PROT_RW: p = PAGE_READWRITE; break;
3425 case MEM_PROT_RWX: p = PAGE_EXECUTE_READWRITE; break;
3426 default:
3427 ShouldNotReachHere();
3428 }
3429
3430 DWORD old_status;
3431
3432 // Strange enough, but on Win32 one can change protection only for committed
3433 // memory, not a big deal anyway, as bytes less or equal than 64K
3434 if (!is_committed) {
3435 commit_memory_or_exit(addr, bytes, prot == MEM_PROT_RWX,
3436 "cannot commit protection page");
3437 }
3438 // One cannot use os::guard_memory() here, as on Win32 guard page
3439 // have different (one-shot) semantics, from MSDN on PAGE_GUARD:
3440 //
3441 // Pages in the region become guard pages. Any attempt to access a guard page
3442 // causes the system to raise a STATUS_GUARD_PAGE exception and turn off
3443 // the guard page status. Guard pages thus act as a one-time access alarm.
3444 return VirtualProtect(addr, bytes, p, &old_status) != 0;
3445 }
3446
3447 bool os::guard_memory(char* addr, size_t bytes) {
3448 DWORD old_status;
3449 return VirtualProtect(addr, bytes, PAGE_READWRITE | PAGE_GUARD, &old_status) != 0;
3450 }
3451
3452 bool os::unguard_memory(char* addr, size_t bytes) {
3453 DWORD old_status;
3454 return VirtualProtect(addr, bytes, PAGE_READWRITE, &old_status) != 0;
3455 }
3456
3457 void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { }
3458 void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { }
3459 void os::numa_make_global(char *addr, size_t bytes) { }
3460 void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { }
3461 bool os::numa_topology_changed() { return false; }
3462 size_t os::numa_get_groups_num() { return MAX2(numa_node_list_holder.get_count(), 1); }
3463 int os::numa_get_group_id() { return 0; }
3464 size_t os::numa_get_leaf_groups(int *ids, size_t size) {
|
3397 // Don't bother the OS with noops.
3398 return true;
3399 }
3400 assert((size_t) addr % os::vm_page_size() == 0, "uncommit on page boundaries");
3401 assert(bytes % os::vm_page_size() == 0, "uncommit in page-sized chunks");
3402 return (VirtualFree(addr, bytes, MEM_DECOMMIT) != 0);
3403 }
3404
3405 bool os::pd_release_memory(char* addr, size_t bytes) {
3406 return VirtualFree(addr, 0, MEM_RELEASE) != 0;
3407 }
3408
3409 bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
3410 return os::commit_memory(addr, size, !ExecMem);
3411 }
3412
3413 bool os::remove_stack_guard_pages(char* addr, size_t size) {
3414 return os::uncommit_memory(addr, size);
3415 }
3416
3417 static bool protect_pages_individually(char* addr, size_t bytes, unsigned int p, DWORD *old_status) {
3418 uint count = 0;
3419 bool ret = false;
3420 size_t bytes_remaining = bytes;
3421 char * next_protect_addr = addr;
3422
3423 // Use VirtualQuery() to get the chunk size.
3424 while (bytes_remaining) {
3425 MEMORY_BASIC_INFORMATION alloc_info;
3426 if (VirtualQuery(next_protect_addr, &alloc_info, sizeof(alloc_info)) == 0) {
3427 return false;
3428 }
3429
3430 size_t bytes_to_protect = MIN2(bytes_remaining, (size_t)alloc_info.RegionSize);
3431 // We used different API at allocate_pages_individually() based on UseNUMAInterleaving,
3432 // but we don't distinguish here as both cases are protected by same API.
3433 ret = VirtualProtect(next_protect_addr, bytes_to_protect, p, old_status) != 0;
3434 assert(ret, "Failed protecting chunk #%u", count);
3435 if (!ret) {
3436 return false;
3437 }
3438
3439 bytes_remaining -= bytes_to_protect;
3440 next_protect_addr += bytes_to_protect;
3441 count++;
3442 }
3443 return ret;
3444 }
3445
3446 // Set protections specified
3447 bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
3448 bool is_committed) {
3449 unsigned int p = 0;
3450 switch (prot) {
3451 case MEM_PROT_NONE: p = PAGE_NOACCESS; break;
3452 case MEM_PROT_READ: p = PAGE_READONLY; break;
3453 case MEM_PROT_RW: p = PAGE_READWRITE; break;
3454 case MEM_PROT_RWX: p = PAGE_EXECUTE_READWRITE; break;
3455 default:
3456 ShouldNotReachHere();
3457 }
3458
3459 DWORD old_status;
3460
3461 // Strange enough, but on Win32 one can change protection only for committed
3462 // memory, not a big deal anyway, as bytes less or equal than 64K
3463 if (!is_committed) {
3464 commit_memory_or_exit(addr, bytes, prot == MEM_PROT_RWX,
3465 "cannot commit protection page");
3466 }
3467 // One cannot use os::guard_memory() here, as on Win32 guard page
3468 // have different (one-shot) semantics, from MSDN on PAGE_GUARD:
3469 //
3470 // Pages in the region become guard pages. Any attempt to access a guard page
3471 // causes the system to raise a STATUS_GUARD_PAGE exception and turn off
3472 // the guard page status. Guard pages thus act as a one-time access alarm.
3473 bool ret;
3474 if (UseNUMAInterleaving) {
3475 // If UseNUMAInterleaving is enabled, the pages may have been allocated a chunk at a time,
3476 // so we must protect the chunks individually.
3477 ret = protect_pages_individually(addr, bytes, p, &old_status);
3478 } else {
3479 ret = VirtualProtect(addr, bytes, p, &old_status) != 0;
3480 }
3481 #ifdef ASSERT
3482 if (!ret) {
3483 int err = os::get_last_error();
3484 char buf[256];
3485 size_t buf_len = os::lasterror(buf, sizeof(buf));
3486 warning("INFO: os::protect_memory(" PTR_FORMAT ", " SIZE_FORMAT
3487 ") failed; error='%s' (DOS error/errno=%d)", addr, bytes,
3488 buf_len != 0 ? buf : "<no_error_string>", err);
3489 }
3490 #endif
3491 return ret;
3492 }
3493
3494 bool os::guard_memory(char* addr, size_t bytes) {
3495 DWORD old_status;
3496 return VirtualProtect(addr, bytes, PAGE_READWRITE | PAGE_GUARD, &old_status) != 0;
3497 }
3498
3499 bool os::unguard_memory(char* addr, size_t bytes) {
3500 DWORD old_status;
3501 return VirtualProtect(addr, bytes, PAGE_READWRITE, &old_status) != 0;
3502 }
3503
3504 void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { }
3505 void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { }
3506 void os::numa_make_global(char *addr, size_t bytes) { }
3507 void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { }
3508 bool os::numa_topology_changed() { return false; }
3509 size_t os::numa_get_groups_num() { return MAX2(numa_node_list_holder.get_count(), 1); }
3510 int os::numa_get_group_id() { return 0; }
3511 size_t os::numa_get_leaf_groups(int *ids, size_t size) {
|