< prev index next >

src/hotspot/os/posix/os_posix.cpp

Print this page

        

*** 38,47 **** --- 38,48 ---- #include <dlfcn.h> #include <pthread.h> #include <semaphore.h> #include <signal.h> + #include <sys/mman.h> #include <sys/resource.h> #include <sys/utsname.h> #include <time.h> #include <unistd.h>
*** 50,59 **** --- 51,74 ---- #ifndef MAX_PID #define MAX_PID INT_MAX #endif #define IS_VALID_PID(p) (p > 0 && p < MAX_PID) + #ifndef MAP_ANONYMOUS + #define MAP_ANONYMOUS MAP_ANON + #endif + + #define check_with_errno(check_type, cond, msg) \ + do { \ + int err = errno; \ + check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err), \ + os::errno_name(err)); \ + } while (false) + + #define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg) + #define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg) + // Check core dump limit and report possible place where core can be found void os::check_dump_limit(char* buffer, size_t bufferSize) { if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) { jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line"); VMError::record_coredump_status(buffer, false);
*** 143,164 **** void os::wait_for_keypress_at_exit(void) { // don't do anything on posix platforms return; } // Multiple threads can race in this code, and can remap over each other with MAP_FIXED, // so on posix, unmap the section at the start and at the end of the chunk that we mapped // rather than unmapping and remapping the whole chunk to get requested alignment. ! char* os::reserve_memory_aligned(size_t size, size_t alignment) { assert((alignment & (os::vm_allocation_granularity() - 1)) == 0, "Alignment must be a multiple of allocation granularity (page size)"); assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned"); size_t extra_size = size + alignment; assert(extra_size >= size, "overflow, size is too large to allow alignment"); ! char* extra_base = os::reserve_memory(extra_size, NULL, alignment); if (extra_base == NULL) { return NULL; } --- 158,306 ---- void os::wait_for_keypress_at_exit(void) { // don't do anything on posix platforms return; } + int os::create_file_for_heap(const char* dir) { + + const char name_template[] = "/jvmheap.XXXXXX"; + + char *fullname = (char*)os::malloc((strlen(dir) + strlen(name_template) + 1), mtInternal); + if (fullname == NULL) { + vm_exit_during_initialization(err_msg("Malloc failed during creation of backing file for heap (%s)", os::strerror(errno))); + return -1; + } + (void)strncpy(fullname, dir, strlen(dir)+1); + (void)strncat(fullname, name_template, strlen(name_template)); + + os::native_path(fullname); + + sigset_t set, oldset; + int ret = sigfillset(&set); + assert_with_errno(ret == 0, "sigfillset returned error"); + + // set the file creation mask. + mode_t file_mode = S_IRUSR | S_IWUSR; + + // create a new file. + int fd = mkstemp(fullname); + + if (fd < 0) { + warning("Could not create file for heap with template %s", fullname); + os::free(fullname); + return -1; + } + + // delete the name from the filesystem. When 'fd' is closed, the file (and space) will be deleted. + ret = unlink(fullname); + assert_with_errno(ret == 0, "unlink returned error"); + + os::free(fullname); + return fd; + } + + static char* reserve_mmapped_memory(size_t bytes, char* requested_addr) { + char * addr; + int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS; + if (requested_addr != NULL) { + assert((uintptr_t)requested_addr % os::vm_page_size() == 0, "Requested address should be aligned to OS page size"); + flags |= MAP_FIXED; + } + + // Map reserved/uncommitted pages PROT_NONE so we fail early if we + // touch an uncommitted page. Otherwise, the read/write might + // succeed if we have enough swap space to back the physical page. + addr = (char*)::mmap(requested_addr, bytes, PROT_NONE, + flags, -1, 0); + + if (addr != MAP_FAILED) { + MemTracker::record_virtual_memory_reserve((address)addr, bytes, CALLER_PC); + return addr; + } + return NULL; + } + + static int util_posix_fallocate(int fd, off_t offset, off_t len) { + #ifdef __APPLE__ + fstore_t store = { F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, len }; + // First we try to get a continuous chunk of disk space + int ret = fcntl(fd, F_PREALLOCATE, &store); + if (ret == -1) { + // Maybe we are too fragmented, try to allocate non-continuous range + store.fst_flags = F_ALLOCATEALL; + ret = fcntl(fd, F_PREALLOCATE, &store); + } + if(ret != -1) { + return ftruncate(fd, len); + } + return -1; + #else + return posix_fallocate(fd, offset, len); + #endif + } + + // 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 (util_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) { + return NULL; + } + if (base != NULL && addr != base) { + if (!os::release_memory(addr, size)) { + warning("Could not release memory on unsuccessful file mapping"); + } + return NULL; + } + return addr; + } + + char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd) { + assert(fd != -1, "File descriptor is not valid"); + assert(base != NULL, "Base cannot be NULL"); + + return map_memory_to_file(base, size, fd); + } + // Multiple threads can race in this code, and can remap over each other with MAP_FIXED, // so on posix, unmap the section at the start and at the end of the chunk that we mapped // rather than unmapping and remapping the whole chunk to get requested alignment. ! char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) { assert((alignment & (os::vm_allocation_granularity() - 1)) == 0, "Alignment must be a multiple of allocation granularity (page size)"); assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned"); size_t extra_size = size + alignment; assert(extra_size >= size, "overflow, size is too large to allow alignment"); ! char* extra_base; ! if (file_desc != -1) { ! // For file mapping, we do not call os:reserve_memory(extra_size, NULL, alignment, file_desc) because ! // we need to deal with shrinking of the file space later when we release extra memory after alignment. ! // We also cannot called os:reserve_memory() with file_desc set to -1 because on aix we might get SHM memory. ! // So here to call a helper function while reserve memory for us. After we have a aligned base, ! // we will replace anonymous mapping with file mapping. ! extra_base = reserve_mmapped_memory(extra_size, NULL); ! if (extra_base != NULL) { ! MemTracker::record_virtual_memory_reserve((address)extra_base, extra_size, CALLER_PC); ! } ! } else { ! extra_base = os::reserve_memory(extra_size, NULL, alignment); ! } if (extra_base == NULL) { return NULL; }
*** 181,190 **** --- 323,339 ---- if (end_offset > 0) { os::release_memory(extra_base + begin_offset + size, end_offset); } + if (file_desc != -1) { + // After we have an aligned address, we can replace anonymous mapping with file mapping + if (replace_existing_mapping_with_file_mapping(aligned_base, size, file_desc) == NULL) { + vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); + } + MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC); + } return aligned_base; } int os::log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { return vsnprintf(buf, len, fmt, args);
*** 1349,1368 **** _crash_protection->restore(); } } } - #define check_with_errno(check_type, cond, msg) \ - do { \ - int err = errno; \ - check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err), \ - os::errno_name(err)); \ - } while (false) - - #define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg) - #define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg) - // POSIX unamed semaphores are not supported on OS X. #ifndef __APPLE__ PosixSemaphore::PosixSemaphore(uint value) { int ret = sem_init(&_semaphore, 0, value); --- 1498,1507 ----
< prev index next >