3449 ::munmap(start, extra_size); 3450 start = NULL; 3451 } 3452 } else { 3453 char* const start_aligned = (char*) align_ptr_up(start, alignment); 3454 char* const end_aligned = start_aligned + bytes; 3455 char* const end = start + extra_size; 3456 if (start_aligned > start) { 3457 ::munmap(start, start_aligned - start); 3458 } 3459 if (end_aligned < end) { 3460 ::munmap(end_aligned, end - end_aligned); 3461 } 3462 start = start_aligned; 3463 } 3464 } 3465 return start; 3466 3467 } 3468 3469 // Reserve memory using mmap(MAP_HUGETLB). 3470 // - bytes shall be a multiple of alignment. 3471 // - req_addr can be NULL. If not NULL, it must be a multiple of alignment. 3472 // - alignment sets the alignment at which memory shall be allocated. 3473 // It must be a multiple of allocation granularity. 3474 // Returns address of memory or NULL. If req_addr was not NULL, will only return 3475 // req_addr or NULL. 3476 char* os::Linux::reserve_memory_special_huge_tlbfs_mixed(size_t bytes, 3477 size_t alignment, 3478 char* req_addr, 3479 bool exec) { 3480 size_t large_page_size = os::large_page_size(); 3481 assert(bytes >= large_page_size, "Shouldn't allocate large pages for small sizes"); 3482 3483 assert(is_ptr_aligned(req_addr, alignment), "Must be"); 3484 assert(is_size_aligned(bytes, alignment), "Must be"); 3485 3486 // First reserve - but not commit - the address range in small pages. 3487 char* const start = anon_mmap_aligned(bytes, alignment, req_addr); 3488 | 3449 ::munmap(start, extra_size); 3450 start = NULL; 3451 } 3452 } else { 3453 char* const start_aligned = (char*) align_ptr_up(start, alignment); 3454 char* const end_aligned = start_aligned + bytes; 3455 char* const end = start + extra_size; 3456 if (start_aligned > start) { 3457 ::munmap(start, start_aligned - start); 3458 } 3459 if (end_aligned < end) { 3460 ::munmap(end_aligned, end - end_aligned); 3461 } 3462 start = start_aligned; 3463 } 3464 } 3465 return start; 3466 3467 } 3468 3469 // Helper function to create a temp file in the given directory 3470 int os::Linux::create_tmpfile(const char* dir, size_t size, bool exec) { 3471 3472 static char name_template[] = "/jvmheap.XXXXXX"; 3473 3474 char fullname[strlen(dir) + sizeof(name_template)]; 3475 (void)strcpy(fullname, dir); 3476 (void)strcat(fullname, name_template); 3477 3478 sigset_t set, oldset; 3479 sigfillset(&set); 3480 3481 // block all signals while we do the file operation 3482 (void)sigprocmask(SIG_BLOCK, &set, &oldset); 3483 3484 // set the file creation mask 3485 mode_t new_mask = exec ? (S_IRUSR | S_IWUSR | S_IXUSR) : (S_IRUSR | S_IWUSR); 3486 mode_t prev_umask = umask(new_mask); 3487 3488 // create a new file 3489 int fd = mkstemp(fullname); 3490 3491 // reset the file creation mask 3492 umask(prev_umask); 3493 3494 if (fd < 0) { 3495 warning("Could not create file for heap"); 3496 return -1; 3497 } 3498 3499 // delete the name from the filesystem. When 'fd' is closed, the file (and space) will be deleted 3500 (void)unlink(fullname); 3501 3502 // reset the signal mask 3503 (void)sigprocmask(SIG_SETMASK, &oldset, NULL); 3504 3505 // allocate space for the file 3506 if ((errno = posix_fallocate(fd, 0, (off_t)size)) != 0) { 3507 warning("Could not allocate sufficient disk space for heap"); 3508 return -1; 3509 } 3510 3511 return fd; 3512 } 3513 3514 // Map the given address range to a temporary file created at the specified directory. 3515 // The address range must already be reserved for guaranteed success. If it not reserved, their could be an error while mapping leading to JVM shutdown 3516 bool os::map_memory_to_file(char* base, size_t size, const char* backingFileDir) { 3517 3518 int fd = os::Linux::create_tmpfile(backingFileDir, size, false); 3519 if (fd == -1) { 3520 vm_exit_during_initialization(err_msg("Could not create temporary file in %s for object heap", backingFileDir)); 3521 return false; 3522 } 3523 int prot = PROT_READ | PROT_WRITE; 3524 char* addr = (char*)mmap(base, size, prot, MAP_SHARED | MAP_FIXED, fd, 0); 3525 3526 if (addr == MAP_FAILED || addr != base) { 3527 close(fd); 3528 vm_exit_during_initialization(err_msg("Error in mapping object heap at the given filesystem dir %s", backingFileDir)); 3529 return false; 3530 } 3531 3532 return true; 3533 } 3534 3535 // Reserve memory using mmap(MAP_HUGETLB). 3536 // - bytes shall be a multiple of alignment. 3537 // - req_addr can be NULL. If not NULL, it must be a multiple of alignment. 3538 // - alignment sets the alignment at which memory shall be allocated. 3539 // It must be a multiple of allocation granularity. 3540 // Returns address of memory or NULL. If req_addr was not NULL, will only return 3541 // req_addr or NULL. 3542 char* os::Linux::reserve_memory_special_huge_tlbfs_mixed(size_t bytes, 3543 size_t alignment, 3544 char* req_addr, 3545 bool exec) { 3546 size_t large_page_size = os::large_page_size(); 3547 assert(bytes >= large_page_size, "Shouldn't allocate large pages for small sizes"); 3548 3549 assert(is_ptr_aligned(req_addr, alignment), "Must be"); 3550 assert(is_size_aligned(bytes, alignment), "Must be"); 3551 3552 // First reserve - but not commit - the address range in small pages. 3553 char* const start = anon_mmap_aligned(bytes, alignment, req_addr); 3554 |