< prev index next >

src/hotspot/os/linux/os_linux.cpp

Print this page

        

*** 151,160 **** --- 151,161 ---- pthread_t os::Linux::_main_thread; int os::Linux::_page_size = -1; bool os::Linux::_supports_fast_thread_cpu_time = false; const char * os::Linux::_glibc_version = NULL; const char * os::Linux::_libpthread_version = NULL; + size_t os::Linux::_default_large_page_size = 0; static jlong initial_time_count=0; static int clock_tics_per_sec = 100;
*** 2946,2955 **** --- 2947,2965 ---- // Define MAP_HUGETLB here so we can build HotSpot on old systems. #ifndef MAP_HUGETLB #define MAP_HUGETLB 0x40000 #endif + // If MAP_HUGETLB is set, and the system supports multiple huge page sizes, + // flag bits [26:31] can be used to encode the log2 of the desired huge page size. + // Otherwise the system's default huge page size will be used. + // See mmap(2) man page for more info (since Linux 3.8). + // https://lwn.net/Articles/533499/ + #ifndef MAP_HUGE_SHIFT + #define MAP_HUGE_SHIFT 26 + #endif + // Define MADV_HUGEPAGE here so we can build HotSpot on old systems. #ifndef MADV_HUGEPAGE #define MADV_HUGEPAGE 14 #endif
*** 3728,3738 **** // Large page support static size_t _large_page_size = 0; ! size_t os::Linux::find_large_page_size() { size_t large_page_size = 0; // large_page_size on Linux is used to round up heap size. x86 uses either // 2M or 4M page, depending on whether PAE (Physical Address Extensions) // mode is enabled. AMD64/EM64T uses 2M page in 64bit mode. IA64 can use --- 3738,3748 ---- // Large page support static size_t _large_page_size = 0; ! size_t os::Linux::find_default_large_page_size() { size_t large_page_size = 0; // large_page_size on Linux is used to round up heap size. x86 uses either // 2M or 4M page, depending on whether PAE (Physical Address Extensions) // mode is enabled. AMD64/EM64T uses 2M page in 64bit mode. IA64 can use
*** 3776,3807 **** } } } fclose(fp); } ! if (!FLAG_IS_DEFAULT(LargePageSizeInBytes) && LargePageSizeInBytes != large_page_size) { ! warning("Setting LargePageSizeInBytes has no effect on this OS. Large page size is " ! SIZE_FORMAT "%s.", byte_size_in_proper_unit(large_page_size), ! proper_unit_for_byte_size(large_page_size)); } ! return large_page_size; } size_t os::Linux::setup_large_page_size() { ! _large_page_size = Linux::find_large_page_size(); const size_t default_page_size = (size_t)Linux::page_size(); if (_large_page_size > default_page_size) { _page_sizes[0] = _large_page_size; _page_sizes[1] = default_page_size; _page_sizes[2] = 0; } return _large_page_size; } bool os::Linux::setup_large_page_type(size_t page_size) { if (FLAG_IS_DEFAULT(UseHugeTLBFS) && FLAG_IS_DEFAULT(UseSHM) && FLAG_IS_DEFAULT(UseTransparentHugePages)) { --- 3786,3857 ---- } } } fclose(fp); } + return large_page_size; + } ! bool os::Linux::is_valid_large_page_size(size_t large_page_size) { ! // We need to scan /sys/kernel/mm/hugepages ! // to discover the available page sizes ! const char* sys_hugepages = "/sys/kernel/mm/hugepages"; ! if (dir_is_empty(sys_hugepages)) { ! return false; } ! DIR *dir = opendir(sys_hugepages); ! if (dir == NULL) { ! return false; ! } ! ! struct dirent *entry; ! size_t page_size; ! bool is_valid = false; ! while ( (entry = readdir(dir)) != NULL) { ! if (entry->d_type == DT_DIR && ! sscanf(entry->d_name, "hugepages-%zukB", &page_size) == 1) { ! // The kernel is using kB, hotspot uses bytes ! if (large_page_size == page_size * K) { ! is_valid = true; ! break; ! } ! } ! } ! closedir(dir); ! return is_valid; } size_t os::Linux::setup_large_page_size() { ! _default_large_page_size = Linux::find_default_large_page_size(); ! _large_page_size = _default_large_page_size; ! ! if (!FLAG_IS_DEFAULT(LargePageSizeInBytes) && LargePageSizeInBytes != _large_page_size ) { ! if (is_valid_large_page_size(LargePageSizeInBytes)) { ! _large_page_size = LargePageSizeInBytes; ! } else { ! warning("Setting LargePageSizeInBytes=" SIZE_FORMAT " has no effect on this OS. Default large page size is " ! SIZE_FORMAT "%s.", ! LargePageSizeInBytes, ! byte_size_in_proper_unit(_large_page_size), proper_unit_for_byte_size(_large_page_size)); ! } ! } ! const size_t default_page_size = (size_t)Linux::page_size(); if (_large_page_size > default_page_size) { _page_sizes[0] = _large_page_size; _page_sizes[1] = default_page_size; _page_sizes[2] = 0; } return _large_page_size; } + size_t os::Linux::default_large_page_size() { + return _default_large_page_size; + } + bool os::Linux::setup_large_page_type(size_t page_size) { if (FLAG_IS_DEFAULT(UseHugeTLBFS) && FLAG_IS_DEFAULT(UseSHM) && FLAG_IS_DEFAULT(UseTransparentHugePages)) {
*** 4026,4038 **** assert(UseLargePages && UseHugeTLBFS, "only for Huge TLBFS large pages"); assert(is_aligned(bytes, os::large_page_size()), "Unaligned size"); assert(is_aligned(req_addr, os::large_page_size()), "Unaligned address"); int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; ! char* addr = (char*)::mmap(req_addr, bytes, prot, ! MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, ! -1, 0); if (addr == MAP_FAILED) { warn_on_large_pages_failure(req_addr, bytes, errno); return NULL; } --- 4076,4091 ---- assert(UseLargePages && UseHugeTLBFS, "only for Huge TLBFS large pages"); assert(is_aligned(bytes, os::large_page_size()), "Unaligned size"); assert(is_aligned(req_addr, os::large_page_size()), "Unaligned address"); int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; ! int flags = MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB; ! ! if (os::large_page_size() != default_large_page_size()) { ! flags |= (exact_log2(os::large_page_size()) << MAP_HUGE_SHIFT); ! } ! char* addr = (char*)::mmap(req_addr, bytes, prot, flags, -1, 0); if (addr == MAP_FAILED) { warn_on_large_pages_failure(req_addr, bytes, errno); return NULL; }
*** 4084,4111 **** ::munmap(start, end - start); return NULL; } int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; ! void* result; // Commit small-paged leading area. if (start != lp_start) { ! result = ::mmap(start, lp_start - start, prot, ! MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, ! -1, 0); if (result == MAP_FAILED) { ::munmap(lp_start, end - lp_start); return NULL; } } // Commit large-paged area. ! result = ::mmap(lp_start, lp_bytes, prot, ! MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED|MAP_HUGETLB, ! -1, 0); if (result == MAP_FAILED) { warn_on_large_pages_failure(lp_start, lp_bytes, errno); // If the mmap above fails, the large pages region will be unmapped and we // have regions before and after with small pages. Release these regions. // --- 4137,4166 ---- ::munmap(start, end - start); return NULL; } int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; ! int flags = MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED; void* result; // Commit small-paged leading area. if (start != lp_start) { ! result = ::mmap(start, lp_start - start, prot, flags, -1, 0); if (result == MAP_FAILED) { ::munmap(lp_start, end - lp_start); return NULL; } } // Commit large-paged area. ! flags |= MAP_HUGETLB; ! ! if (os::large_page_size() != default_large_page_size()) { ! flags |= (exact_log2(os::large_page_size()) << MAP_HUGE_SHIFT); ! } ! ! result = ::mmap(lp_start, lp_bytes, prot, flags, -1, 0); if (result == MAP_FAILED) { warn_on_large_pages_failure(lp_start, lp_bytes, errno); // If the mmap above fails, the large pages region will be unmapped and we // have regions before and after with small pages. Release these regions. //
< prev index next >