--- old/src/os/linux/vm/os_linux.cpp 2016-12-12 09:51:34.862525886 -0800 +++ new/src/os/linux/vm/os_linux.cpp 2016-12-12 09:51:34.746525888 -0800 @@ -3086,7 +3086,10 @@ } char* os::pd_reserve_memory(size_t bytes, char* requested_addr, - size_t alignment_hint) { + size_t alignment_hint, int file_desc) { + if (file_desc != -1) { + return map_memory_to_file(requested_addr, bytes, file_desc); + } return anon_mmap(requested_addr, bytes, (requested_addr != NULL)); } @@ -3541,6 +3544,74 @@ return addr; } +// Helper function to create a temp file in the given directory. +int os::create_file_for_heap(const char* dir, size_t size) { + + const char name_template[] = "/jvmheap.XXXXXX"; + + char *fullname = (char*)alloca(strlen(dir) + sizeof(name_template)); + (void)strcpy(fullname, dir); + (void)strcat(fullname, name_template); + + sigset_t set, oldset; + sigfillset(&set); + + // block all signals while we do the file operation. + (void)sigprocmask(SIG_BLOCK, &set, &oldset); + + // set the file creation mask. + mode_t new_mask = S_IRUSR | S_IWUSR; + mode_t prev_umask = umask(new_mask); + + // create a new file. + int fd = mkstemp(fullname); + + // reset the file creation mask. + umask(prev_umask); + + if (fd < 0) { + warning("Failure to create file %s for heap", fullname); + return -1; + } + + // delete the name from the filesystem. When 'fd' is closed, the file (and space) will be deleted. + (void)unlink(fullname); + + // reset the signal mask. + (void)sigprocmask(SIG_SETMASK, &oldset, NULL); + + return fd; +} + +// Map the given address range to the provided file descriptor. +char* os::map_memory_to_file(char* base, size_t size, int fd) { + assert(fd != -1, "File descriptor is not valid"); + + // allocate space for the file + if ((errno = posix_fallocate(fd, 0, (off_t)size)) != 0) { + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); + return NULL; + } + + int prot = PROT_READ | PROT_WRITE; + int flags = MAP_SHARED; + if( base != NULL) { + flags |= MAP_FIXED; + } + char* addr = (char*)mmap(base, size, prot, flags, fd, 0); + + if (addr == MAP_FAILED || (base != NULL && addr != base)) { + if (addr != MAP_FAILED) { + if (!pd_release_memory(addr, size)) { + warning("Could not release memory on unsuccessful file mapping"); + } + } + return NULL; + } + + return addr; +} + // Reserve memory using mmap(MAP_HUGETLB). // - bytes shall be a multiple of alignment. // - req_addr can be NULL. If not NULL, it must be a multiple of alignment. @@ -3731,7 +3802,7 @@ // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). -char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { +char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) { const int max_tries = 10; char* base[max_tries]; size_t size[max_tries]; @@ -3751,7 +3822,9 @@ // if kernel honors the hint then we can return immediately. char * addr = anon_mmap(requested_addr, bytes, false); if (addr == requested_addr) { - return requested_addr; + if (file_desc == -1 || map_memory_to_file(requested_addr, bytes, file_desc) != NULL) { + return requested_addr; + } } if (addr != NULL) { @@ -3799,6 +3872,9 @@ } if (i < max_tries) { + if (file_desc != -1 && map_memory_to_file(requested_addr, bytes, file_desc) == NULL) { + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); + } return requested_addr; } else { return NULL;