8261894: Remove support for UseSHM

Reviewed-by: dholmes, ayang
This commit is contained in:
Thomas Stuefe 2023-10-10 11:10:17 +00:00
parent ad7a8e86e0
commit c2abf120bc
8 changed files with 85 additions and 625 deletions

View File

@ -44,18 +44,12 @@
product(bool, UseLinuxPosixThreadCPUClocks, true, \ product(bool, UseLinuxPosixThreadCPUClocks, true, \
"enable fast Linux Posix clocks where available") \ "enable fast Linux Posix clocks where available") \
\ \
product(bool, UseHugeTLBFS, false, \
"Use MAP_HUGETLB for large pages") \
\
product(bool, UseTransparentHugePages, false, \ product(bool, UseTransparentHugePages, false, \
"Use MADV_HUGEPAGE for large pages") \ "Use MADV_HUGEPAGE for large pages") \
\ \
product(bool, LoadExecStackDllInVMThread, true, \ product(bool, LoadExecStackDllInVMThread, true, \
"Load DLLs with executable-stack attribute in the VM Thread") \ "Load DLLs with executable-stack attribute in the VM Thread") \
\ \
product(bool, UseSHM, false, \
"Use SYSV shared memory for large pages") \
\
product(bool, UseContainerSupport, true, \ product(bool, UseContainerSupport, true, \
"Enable detection and runtime container configuration support") \ "Enable detection and runtime container configuration support") \
\ \

View File

@ -111,7 +111,6 @@
# include <syscall.h> # include <syscall.h>
# include <sys/sysinfo.h> # include <sys/sysinfo.h>
# include <sys/ipc.h> # include <sys/ipc.h>
# include <sys/shm.h>
# include <link.h> # include <link.h>
# include <stdint.h> # include <stdint.h>
# include <inttypes.h> # include <inttypes.h>
@ -3607,14 +3606,17 @@ bool os::unguard_memory(char* addr, size_t size) {
return linux_mprotect(addr, size, PROT_READ|PROT_WRITE); return linux_mprotect(addr, size, PROT_READ|PROT_WRITE);
} }
int os::Linux::hugetlbfs_page_size_flag(size_t page_size) { static int hugetlbfs_page_size_flag(size_t page_size) {
if (page_size != HugePages::default_static_hugepage_size()) { if (page_size != HugePages::default_static_hugepage_size()) {
return (exact_log2(page_size) << MAP_HUGE_SHIFT); return (exact_log2(page_size) << MAP_HUGE_SHIFT);
} }
return 0; return 0;
} }
bool os::Linux::hugetlbfs_sanity_check(bool warn, size_t page_size) { static bool hugetlbfs_sanity_check(size_t page_size) {
const os::PageSizes page_sizes = HugePages::static_info().pagesizes();
assert(page_sizes.contains(page_size), "Invalid page sizes passed");
// Include the page size flag to ensure we sanity check the correct page size. // Include the page size flag to ensure we sanity check the correct page size.
int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB | hugetlbfs_page_size_flag(page_size); int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB | hugetlbfs_page_size_flag(page_size);
void *p = mmap(nullptr, page_size, PROT_READ|PROT_WRITE, flags, -1, 0); void *p = mmap(nullptr, page_size, PROT_READ|PROT_WRITE, flags, -1, 0);
@ -3628,9 +3630,9 @@ bool os::Linux::hugetlbfs_sanity_check(bool warn, size_t page_size) {
"checking if smaller large page sizes are usable", "checking if smaller large page sizes are usable",
byte_size_in_exact_unit(page_size), byte_size_in_exact_unit(page_size),
exact_unit_for_byte_size(page_size)); exact_unit_for_byte_size(page_size));
for (size_t page_size_ = _page_sizes.next_smaller(page_size); for (size_t page_size_ = page_sizes.next_smaller(page_size);
page_size_ != os::vm_page_size(); page_size_ > os::vm_page_size();
page_size_ = _page_sizes.next_smaller(page_size_)) { page_size_ = page_sizes.next_smaller(page_size_)) {
flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB | hugetlbfs_page_size_flag(page_size_); flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB | hugetlbfs_page_size_flag(page_size_);
p = mmap(nullptr, page_size_, PROT_READ|PROT_WRITE, flags, -1, 0); p = mmap(nullptr, page_size_, PROT_READ|PROT_WRITE, flags, -1, 0);
if (p != MAP_FAILED) { if (p != MAP_FAILED) {
@ -3644,37 +3646,9 @@ bool os::Linux::hugetlbfs_sanity_check(bool warn, size_t page_size) {
} }
} }
if (warn) {
warning("HugeTLBFS is not configured or not supported by the operating system.");
}
return false; return false;
} }
bool os::Linux::shm_hugetlbfs_sanity_check(bool warn, size_t page_size) {
// Try to create a large shared memory segment.
int shmid = shmget(IPC_PRIVATE, page_size, SHM_HUGETLB|IPC_CREAT|SHM_R|SHM_W);
if (shmid == -1) {
// Possible reasons for shmget failure:
// 1. shmmax is too small for the request.
// > check shmmax value: cat /proc/sys/kernel/shmmax
// > increase shmmax value: echo "new_value" > /proc/sys/kernel/shmmax
// 2. not enough large page memory.
// > check available large pages: cat /proc/meminfo
// > increase amount of large pages:
// sysctl -w vm.nr_hugepages=new_value
// > For more information regarding large pages please refer to:
// https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
if (warn) {
warning("Large pages using UseSHM are not configured on this system.");
}
return false;
}
// Managed to create a segment, now delete it.
shmctl(shmid, IPC_RMID, nullptr);
return true;
}
// From the coredump_filter documentation: // From the coredump_filter documentation:
// //
// - (bit 0) anonymous private memory // - (bit 0) anonymous private memory
@ -3722,56 +3696,13 @@ void warn_no_large_pages_configured() {
} }
} }
bool os::Linux::setup_large_page_type(size_t page_size) {
if (FLAG_IS_DEFAULT(UseHugeTLBFS) &&
FLAG_IS_DEFAULT(UseSHM) &&
FLAG_IS_DEFAULT(UseTransparentHugePages)) {
// The type of large pages has not been specified by the user.
// Try UseHugeTLBFS and then UseSHM.
UseHugeTLBFS = UseSHM = true;
// Don't try UseTransparentHugePages since there are known
// performance issues with it turned on. This might change in the future.
UseTransparentHugePages = false;
}
if (UseTransparentHugePages) {
UseHugeTLBFS = false;
UseSHM = false;
return true;
}
if (UseHugeTLBFS) {
bool warn_on_failure = !FLAG_IS_DEFAULT(UseHugeTLBFS);
if (hugetlbfs_sanity_check(warn_on_failure, page_size)) {
UseSHM = false;
return true;
}
UseHugeTLBFS = false;
}
if (UseSHM) {
bool warn_on_failure = !FLAG_IS_DEFAULT(UseSHM);
if (shm_hugetlbfs_sanity_check(warn_on_failure, page_size)) {
return true;
}
UseSHM = false;
}
warn_no_large_pages_configured();
return false;
}
struct LargePageInitializationLoggerMark { struct LargePageInitializationLoggerMark {
~LargePageInitializationLoggerMark() { ~LargePageInitializationLoggerMark() {
LogTarget(Info, pagesize) lt; LogTarget(Info, pagesize) lt;
if (lt.is_enabled()) { if (lt.is_enabled()) {
LogStream ls(lt); LogStream ls(lt);
if (UseLargePages) { if (UseLargePages) {
ls.print_cr("UseLargePages=1, UseTransparentHugePages=%d, UseHugeTLBFS=%d, UseSHM=%d", ls.print_cr("UseLargePages=1, UseTransparentHugePages=%d", UseTransparentHugePages);
UseTransparentHugePages, UseHugeTLBFS, UseSHM);
ls.print("Large page support enabled. Usable page sizes: "); ls.print("Large page support enabled. Usable page sizes: ");
os::page_sizes().print_on(&ls); os::page_sizes().print_on(&ls);
ls.print_cr(". Default large page size: " EXACTFMT ".", EXACTFMTARGS(os::large_page_size())); ls.print_cr(". Default large page size: " EXACTFMT ".", EXACTFMTARGS(os::large_page_size()));
@ -3805,19 +3736,14 @@ void os::large_page_init() {
// 1) Handle the case where we do not want to use huge pages // 1) Handle the case where we do not want to use huge pages
if (!UseLargePages && if (!UseLargePages &&
!UseTransparentHugePages && !UseTransparentHugePages) {
!UseHugeTLBFS &&
!UseSHM) {
// Not using large pages. // Not using large pages.
return; return;
} }
if (!FLAG_IS_DEFAULT(UseLargePages) && !UseLargePages) { if (!FLAG_IS_DEFAULT(UseLargePages) && !UseLargePages) {
// The user explicitly turned off large pages. // The user explicitly turned off large pages.
// Ignore the rest of the large pages flags.
UseTransparentHugePages = false; UseTransparentHugePages = false;
UseHugeTLBFS = false;
UseSHM = false;
return; return;
} }
@ -3826,12 +3752,12 @@ void os::large_page_init() {
if (!FLAG_IS_DEFAULT(UseTransparentHugePages)) { if (!FLAG_IS_DEFAULT(UseTransparentHugePages)) {
log_warning(pagesize)("UseTransparentHugePages disabled, transparent huge pages are not supported by the operating system."); log_warning(pagesize)("UseTransparentHugePages disabled, transparent huge pages are not supported by the operating system.");
} }
UseLargePages = UseTransparentHugePages = UseHugeTLBFS = UseSHM = false; UseLargePages = UseTransparentHugePages = false;
return; return;
} }
if (!UseTransparentHugePages && !HugePages::supports_static_hugepages()) { if (!UseTransparentHugePages && !HugePages::supports_static_hugepages()) {
warn_no_large_pages_configured(); warn_no_large_pages_configured();
UseLargePages = UseTransparentHugePages = UseHugeTLBFS = UseSHM = false; UseLargePages = UseTransparentHugePages = false;
return; return;
} }
@ -3855,6 +3781,8 @@ void os::large_page_init() {
// 3) Consistency check and post-processing // 3) Consistency check and post-processing
size_t large_page_size = 0;
// Check LargePageSizeInBytes matches an available page size and if so set _large_page_size // Check LargePageSizeInBytes matches an available page size and if so set _large_page_size
// using LargePageSizeInBytes as the maximum allowed large page size. If LargePageSizeInBytes // using LargePageSizeInBytes as the maximum allowed large page size. If LargePageSizeInBytes
// doesn't match an available page size set _large_page_size to default_large_page_size // doesn't match an available page size set _large_page_size to default_large_page_size
@ -3862,30 +3790,40 @@ void os::large_page_init() {
if (FLAG_IS_DEFAULT(LargePageSizeInBytes) || if (FLAG_IS_DEFAULT(LargePageSizeInBytes) ||
LargePageSizeInBytes == 0 || LargePageSizeInBytes == 0 ||
LargePageSizeInBytes == default_large_page_size) { LargePageSizeInBytes == default_large_page_size) {
_large_page_size = default_large_page_size; large_page_size = default_large_page_size;
log_info(pagesize)("Using the default large page size: " SIZE_FORMAT "%s", log_info(pagesize)("Using the default large page size: " SIZE_FORMAT "%s",
byte_size_in_exact_unit(_large_page_size), byte_size_in_exact_unit(large_page_size),
exact_unit_for_byte_size(_large_page_size)); exact_unit_for_byte_size(large_page_size));
} else { } else {
if (all_large_pages.contains(LargePageSizeInBytes)) { if (all_large_pages.contains(LargePageSizeInBytes)) {
_large_page_size = LargePageSizeInBytes; large_page_size = LargePageSizeInBytes;
log_info(pagesize)("Overriding default large page size (" SIZE_FORMAT "%s) " log_info(pagesize)("Overriding default large page size (" SIZE_FORMAT "%s) "
"using LargePageSizeInBytes: " SIZE_FORMAT "%s", "using LargePageSizeInBytes: " SIZE_FORMAT "%s",
byte_size_in_exact_unit(default_large_page_size), byte_size_in_exact_unit(default_large_page_size),
exact_unit_for_byte_size(default_large_page_size), exact_unit_for_byte_size(default_large_page_size),
byte_size_in_exact_unit(_large_page_size), byte_size_in_exact_unit(large_page_size),
exact_unit_for_byte_size(_large_page_size)); exact_unit_for_byte_size(large_page_size));
} else { } else {
_large_page_size = default_large_page_size; large_page_size = default_large_page_size;
log_info(pagesize)("LargePageSizeInBytes is not a valid large page size (" SIZE_FORMAT "%s) " log_info(pagesize)("LargePageSizeInBytes is not a valid large page size (" SIZE_FORMAT "%s) "
"using the default large page size: " SIZE_FORMAT "%s", "using the default large page size: " SIZE_FORMAT "%s",
byte_size_in_exact_unit(LargePageSizeInBytes), byte_size_in_exact_unit(LargePageSizeInBytes),
exact_unit_for_byte_size(LargePageSizeInBytes), exact_unit_for_byte_size(LargePageSizeInBytes),
byte_size_in_exact_unit(_large_page_size), byte_size_in_exact_unit(large_page_size),
exact_unit_for_byte_size(_large_page_size)); exact_unit_for_byte_size(large_page_size));
} }
} }
// Do an additional sanity check to see if we can use the desired large page size
if (!hugetlbfs_sanity_check(large_page_size)) {
warn_no_large_pages_configured();
UseLargePages = false;
UseTransparentHugePages = false;
return;
}
_large_page_size = large_page_size;
// Populate _page_sizes with large page sizes less than or equal to // Populate _page_sizes with large page sizes less than or equal to
// _large_page_size. // _large_page_size.
for (size_t page_size = _large_page_size; page_size != 0; for (size_t page_size = _large_page_size; page_size != 0;
@ -3894,156 +3832,9 @@ void os::large_page_init() {
} }
} }
// Now determine the type of large pages to use:
UseLargePages = os::Linux::setup_large_page_type(_large_page_size);
set_coredump_filter(LARGEPAGES_BIT); set_coredump_filter(LARGEPAGES_BIT);
} }
#ifndef SHM_HUGETLB
#define SHM_HUGETLB 04000
#endif
#define shm_warning_format(format, ...) \
do { \
if (UseLargePages && \
(!FLAG_IS_DEFAULT(UseLargePages) || \
!FLAG_IS_DEFAULT(UseSHM) || \
!FLAG_IS_DEFAULT(LargePageSizeInBytes))) { \
warning(format, __VA_ARGS__); \
} \
} while (0)
#define shm_warning(str) shm_warning_format("%s", str)
#define shm_warning_with_errno(str) \
do { \
int err = errno; \
shm_warning_format(str " (error = %d)", err); \
} while (0)
static char* shmat_with_alignment(int shmid, size_t bytes, size_t alignment) {
assert(is_aligned(bytes, alignment), "Must be divisible by the alignment");
if (!is_aligned(alignment, SHMLBA)) {
assert(false, "Code below assumes that alignment is at least SHMLBA aligned");
return nullptr;
}
// To ensure that we get 'alignment' aligned memory from shmat,
// we pre-reserve aligned virtual memory and then attach to that.
char* pre_reserved_addr = anon_mmap_aligned(nullptr /* req_addr */, bytes, alignment);
if (pre_reserved_addr == nullptr) {
// Couldn't pre-reserve aligned memory.
shm_warning("Failed to pre-reserve aligned memory for shmat.");
return nullptr;
}
// SHM_REMAP is needed to allow shmat to map over an existing mapping.
char* addr = (char*)shmat(shmid, pre_reserved_addr, SHM_REMAP);
if ((intptr_t)addr == -1) {
int err = errno;
shm_warning_with_errno("Failed to attach shared memory.");
assert(err != EACCES, "Unexpected error");
assert(err != EIDRM, "Unexpected error");
assert(err != EINVAL, "Unexpected error");
// Since we don't know if the kernel unmapped the pre-reserved memory area
// we can't unmap it, since that would potentially unmap memory that was
// mapped from other threads.
return nullptr;
}
return addr;
}
static char* shmat_at_address(int shmid, char* req_addr) {
if (!is_aligned(req_addr, SHMLBA)) {
assert(false, "Requested address needs to be SHMLBA aligned");
return nullptr;
}
char* addr = (char*)shmat(shmid, req_addr, 0);
if ((intptr_t)addr == -1) {
shm_warning_with_errno("Failed to attach shared memory.");
return nullptr;
}
return addr;
}
static char* shmat_large_pages(int shmid, size_t bytes, size_t alignment, char* req_addr) {
// If a req_addr has been provided, we assume that the caller has already aligned the address.
if (req_addr != nullptr) {
assert(is_aligned(req_addr, os::large_page_size()), "Must be divisible by the large page size");
assert(is_aligned(req_addr, alignment), "Must be divisible by given alignment");
return shmat_at_address(shmid, req_addr);
}
// Since shmid has been setup with SHM_HUGETLB, shmat will automatically
// return large page size aligned memory addresses when req_addr == nullptr.
// However, if the alignment is larger than the large page size, we have
// to manually ensure that the memory returned is 'alignment' aligned.
if (alignment > os::large_page_size()) {
assert(is_aligned(alignment, os::large_page_size()), "Must be divisible by the large page size");
return shmat_with_alignment(shmid, bytes, alignment);
} else {
return shmat_at_address(shmid, nullptr);
}
}
char* os::Linux::reserve_memory_special_shm(size_t bytes, size_t alignment,
char* req_addr, bool exec) {
// "exec" is passed in but not used. Creating the shared image for
// the code cache doesn't have an SHM_X executable permission to check.
assert(UseLargePages && UseSHM, "only for SHM large pages");
assert(is_aligned(req_addr, os::large_page_size()), "Unaligned address");
assert(is_aligned(req_addr, alignment), "Unaligned address");
if (!is_aligned(bytes, os::large_page_size())) {
return nullptr; // Fallback to small pages.
}
// Create a large shared memory region to attach to based on size.
// Currently, size is the total size of the heap.
int shmid = shmget(IPC_PRIVATE, bytes, SHM_HUGETLB|IPC_CREAT|SHM_R|SHM_W);
if (shmid == -1) {
// Possible reasons for shmget failure:
// 1. shmmax is too small for the request.
// > check shmmax value: cat /proc/sys/kernel/shmmax
// > increase shmmax value: echo "new_value" > /proc/sys/kernel/shmmax
// 2. not enough large page memory.
// > check available large pages: cat /proc/meminfo
// > increase amount of large pages:
// sysctl -w vm.nr_hugepages=new_value
// > For more information regarding large pages please refer to:
// https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
// Note 1: different Linux may use different name for this property,
// e.g. on Redhat AS-3 it is "hugetlb_pool".
// Note 2: it's possible there's enough physical memory available but
// they are so fragmented after a long run that they can't
// coalesce into large pages. Try to reserve large pages when
// the system is still "fresh".
shm_warning_with_errno("Failed to reserve shared memory.");
return nullptr;
}
// Attach to the region.
char* addr = shmat_large_pages(shmid, bytes, alignment, req_addr);
// Remove shmid. If shmat() is successful, the actual shared memory segment
// will be deleted when it's detached by shmdt() or when the process
// terminates. If shmat() is not successful this will remove the shared
// segment immediately.
shmctl(shmid, IPC_RMID, nullptr);
return addr;
}
static void log_on_commit_special_failure(char* req_addr, size_t bytes, static void log_on_commit_special_failure(char* req_addr, size_t bytes,
size_t page_size, int error) { size_t page_size, int error) {
assert(error == ENOMEM, "Only expect to fail if no memory is available"); assert(error == ENOMEM, "Only expect to fail if no memory is available");
@ -4054,11 +3845,11 @@ static void log_on_commit_special_failure(char* req_addr, size_t bytes,
byte_size_in_exact_unit(page_size), exact_unit_for_byte_size(page_size), error); byte_size_in_exact_unit(page_size), exact_unit_for_byte_size(page_size), error);
} }
bool os::Linux::commit_memory_special(size_t bytes, static bool commit_memory_special(size_t bytes,
size_t page_size, size_t page_size,
char* req_addr, char* req_addr,
bool exec) { bool exec) {
assert(UseLargePages && UseHugeTLBFS, "Should only get here when HugeTLBFS large pages are used"); assert(UseLargePages && !UseTransparentHugePages, "Should only get here for static hugepage mode (+UseLargePages)");
assert(is_aligned(bytes, page_size), "Unaligned size"); assert(is_aligned(bytes, page_size), "Unaligned size");
assert(is_aligned(req_addr, page_size), "Unaligned address"); assert(is_aligned(req_addr, page_size), "Unaligned address");
assert(req_addr != nullptr, "Must have a requested address for special mappings"); assert(req_addr != nullptr, "Must have a requested address for special mappings");
@ -4087,16 +3878,17 @@ bool os::Linux::commit_memory_special(size_t bytes,
return true; return true;
} }
char* os::Linux::reserve_memory_special_huge_tlbfs(size_t bytes, static char* reserve_memory_special_huge_tlbfs(size_t bytes,
size_t alignment, size_t alignment,
size_t page_size, size_t page_size,
char* req_addr, char* req_addr,
bool exec) { bool exec) {
assert(UseLargePages && UseHugeTLBFS, "only for Huge TLBFS large pages"); const os::PageSizes page_sizes = HugePages::static_info().pagesizes();
assert(UseLargePages, "only for Huge TLBFS large pages");
assert(is_aligned(req_addr, alignment), "Must be"); assert(is_aligned(req_addr, alignment), "Must be");
assert(is_aligned(req_addr, page_size), "Must be"); assert(is_aligned(req_addr, page_size), "Must be");
assert(is_aligned(alignment, os::vm_allocation_granularity()), "Must be"); assert(is_aligned(alignment, os::vm_allocation_granularity()), "Must be");
assert(_page_sizes.contains(page_size), "Must be a valid page size"); assert(page_sizes.contains(page_size), "Must be a valid page size");
assert(page_size > os::vm_page_size(), "Must be a large page size"); assert(page_size > os::vm_page_size(), "Must be a large page size");
assert(bytes >= page_size, "Shouldn't allocate large pages for small sizes"); assert(bytes >= page_size, "Shouldn't allocate large pages for small sizes");
@ -4149,14 +3941,7 @@ char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_
char* req_addr, bool exec) { char* req_addr, bool exec) {
assert(UseLargePages, "only for large pages"); assert(UseLargePages, "only for large pages");
char* addr; char* const addr = reserve_memory_special_huge_tlbfs(bytes, alignment, page_size, req_addr, exec);
if (UseSHM) {
// No support for using specific page sizes with SHM.
addr = os::Linux::reserve_memory_special_shm(bytes, alignment, req_addr, exec);
} else {
assert(UseHugeTLBFS, "must be");
addr = os::Linux::reserve_memory_special_huge_tlbfs(bytes, alignment, page_size, req_addr, exec);
}
if (addr != nullptr) { if (addr != nullptr) {
if (UseNUMAInterleaving) { if (UseNUMAInterleaving) {
@ -4167,45 +3952,29 @@ char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_
return addr; return addr;
} }
bool os::Linux::release_memory_special_shm(char* base, size_t bytes) {
// detaching the SHM segment will also delete it, see reserve_memory_special_shm()
return shmdt(base) == 0;
}
bool os::Linux::release_memory_special_huge_tlbfs(char* base, size_t bytes) {
return pd_release_memory(base, bytes);
}
bool os::pd_release_memory_special(char* base, size_t bytes) { bool os::pd_release_memory_special(char* base, size_t bytes) {
assert(UseLargePages, "only for large pages"); assert(UseLargePages, "only for large pages");
bool res; // Plain munmap is sufficient
return pd_release_memory(base, bytes);
if (UseSHM) {
res = os::Linux::release_memory_special_shm(base, bytes);
} else {
assert(UseHugeTLBFS, "must be");
res = os::Linux::release_memory_special_huge_tlbfs(base, bytes);
}
return res;
} }
size_t os::large_page_size() { size_t os::large_page_size() {
return _large_page_size; return _large_page_size;
} }
// With SysV SHM the entire memory region must be allocated as shared // static hugepages (hugetlbfs) allow application to commit large page memory
// memory. // on demand.
// HugeTLBFS allows application to commit large page memory on demand. // However, when committing memory with hugepages fails, the region
// However, when committing memory with HugeTLBFS fails, the region
// that was supposed to be committed will lose the old reservation // that was supposed to be committed will lose the old reservation
// and allow other threads to steal that memory region. Because of this // and allow other threads to steal that memory region. Because of this
// behavior we can't commit HugeTLBFS memory. // behavior we can't commit hugetlbfs memory. Instead, we commit that
// memory at reservation.
bool os::can_commit_large_page_memory() { bool os::can_commit_large_page_memory() {
return UseTransparentHugePages; return UseTransparentHugePages;
} }
bool os::can_execute_large_page_memory() { bool os::can_execute_large_page_memory() {
return UseTransparentHugePages || UseHugeTLBFS; return UseTransparentHugePages;
} }
char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {
@ -4561,12 +4330,11 @@ void os::Linux::numa_init() {
} }
if (UseParallelGC && UseNUMA && UseLargePages && !can_commit_large_page_memory()) { if (UseParallelGC && UseNUMA && UseLargePages && !can_commit_large_page_memory()) {
// With SHM and HugeTLBFS large pages we cannot uncommit a page, so there's no way // With static large pages we cannot uncommit a page, so there's no way
// we can make the adaptive lgrp chunk resizing work. If the user specified both // we can make the adaptive lgrp chunk resizing work. If the user specified both
// UseNUMA and UseLargePages (or UseSHM/UseHugeTLBFS) on the command line - warn // UseNUMA and UseLargePages on the command line - warn and disable adaptive resizing.
// and disable adaptive resizing.
if (UseAdaptiveSizePolicy || UseAdaptiveNUMAChunkSizing) { if (UseAdaptiveSizePolicy || UseAdaptiveNUMAChunkSizing) {
warning("UseNUMA is not fully compatible with SHM/HugeTLBFS large pages, " warning("UseNUMA is not fully compatible with +UseLargePages, "
"disabling adaptive resizing (-XX:-UseAdaptiveSizePolicy -XX:-UseAdaptiveNUMAChunkSizing)"); "disabling adaptive resizing (-XX:-UseAdaptiveSizePolicy -XX:-UseAdaptiveNUMAChunkSizing)");
UseAdaptiveSizePolicy = false; UseAdaptiveSizePolicy = false;
UseAdaptiveNUMAChunkSizing = false; UseAdaptiveNUMAChunkSizing = false;

View File

@ -33,7 +33,6 @@ class os::Linux {
friend class CgroupSubsystem; friend class CgroupSubsystem;
friend class os; friend class os;
friend class OSContainer; friend class OSContainer;
friend class TestReserveMemorySpecial;
static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *); static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *);
static int (*_pthread_setname_np)(pthread_t, const char*); static int (*_pthread_setname_np)(pthread_t, const char*);
@ -75,20 +74,6 @@ class os::Linux {
static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; } static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; }
static GrowableArray<int>* nindex_to_node() { return _nindex_to_node; } static GrowableArray<int>* nindex_to_node() { return _nindex_to_node; }
static bool setup_large_page_type(size_t page_size);
static bool hugetlbfs_sanity_check(bool warn, size_t page_size);
static bool shm_hugetlbfs_sanity_check(bool warn, size_t page_size);
static int hugetlbfs_page_size_flag(size_t page_size);
static char* reserve_memory_special_shm(size_t bytes, size_t alignment, char* req_addr, bool exec);
static char* reserve_memory_special_huge_tlbfs(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec);
static bool commit_memory_special(size_t bytes, size_t page_size, char* req_addr, bool exec);
static bool release_memory_special_impl(char* base, size_t bytes);
static bool release_memory_special_shm(char* base, size_t bytes);
static bool release_memory_special_huge_tlbfs(char* base, size_t bytes);
static void print_process_memory_info(outputStream* st); static void print_process_memory_info(outputStream* st);
static void print_system_memory_info(outputStream* st); static void print_system_memory_info(outputStream* st);
static bool print_container_info(outputStream* st); static bool print_container_info(outputStream* st);

View File

@ -526,6 +526,11 @@ static SpecialFlag const special_jvm_flags[] = {
{ "MetaspaceReclaimPolicy", JDK_Version::undefined(), JDK_Version::jdk(21), JDK_Version::undefined() }, { "MetaspaceReclaimPolicy", JDK_Version::undefined(), JDK_Version::jdk(21), JDK_Version::undefined() },
{ "DoReserveCopyInSuperWord", JDK_Version::undefined(), JDK_Version::jdk(22), JDK_Version::jdk(23) }, { "DoReserveCopyInSuperWord", JDK_Version::undefined(), JDK_Version::jdk(22), JDK_Version::jdk(23) },
#ifdef LINUX
{ "UseHugeTLBFS", JDK_Version::undefined(), JDK_Version::jdk(22), JDK_Version::jdk(23) },
{ "UseSHM", JDK_Version::undefined(), JDK_Version::jdk(22), JDK_Version::jdk(23) },
#endif
#ifdef ASSERT #ifdef ASSERT
{ "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() }, { "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() },
#endif #endif

View File

@ -37,6 +37,7 @@
#include <sys/mman.h> #include <sys/mman.h>
static bool using_static_hugepages() { return UseLargePages && !UseTransparentHugePages; }
namespace { namespace {
static void small_page_write(void* addr, size_t size) { static void small_page_write(void* addr, size_t size) {
@ -53,29 +54,16 @@ namespace {
const size_t _size; const size_t _size;
public: public:
static char* reserve_memory_special_huge_tlbfs(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec) { static char* reserve_memory_special_huge_tlbfs(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec) {
return os::Linux::reserve_memory_special_huge_tlbfs(bytes, alignment, page_size, req_addr, exec); return os::reserve_memory_special(bytes, alignment, page_size, req_addr, exec);
} }
HugeTlbfsMemory(char* const ptr, size_t size) : _ptr(ptr), _size(size) { } HugeTlbfsMemory(char* const ptr, size_t size) : _ptr(ptr), _size(size) { }
~HugeTlbfsMemory() { ~HugeTlbfsMemory() {
if (_ptr != NULL) { if (_ptr != NULL) {
os::Linux::release_memory_special_huge_tlbfs(_ptr, _size); os::release_memory_special(_ptr, _size);
} }
} }
}; };
class ShmMemory : private ::os::Linux {
char* const _ptr;
const size_t _size;
public:
static char* reserve_memory_special_shm(size_t bytes, size_t alignment, char* req_addr, bool exec) {
return os::Linux::reserve_memory_special_shm(bytes, alignment, req_addr, exec);
}
ShmMemory(char* const ptr, size_t size) : _ptr(ptr), _size(size) { }
~ShmMemory() {
os::Linux::release_memory_special_shm(_ptr, _size);
}
};
// have to use these functions, as gtest's _PRED macros don't like is_aligned // have to use these functions, as gtest's _PRED macros don't like is_aligned
// nor (is_aligned<size_t, size_t>) // nor (is_aligned<size_t, size_t>)
static bool is_size_aligned(size_t size, size_t alignment) { static bool is_size_aligned(size_t size, size_t alignment) {
@ -84,22 +72,10 @@ namespace {
static bool is_ptr_aligned(char* ptr, size_t alignment) { static bool is_ptr_aligned(char* ptr, size_t alignment) {
return is_aligned(ptr, alignment); return is_aligned(ptr, alignment);
} }
static void test_reserve_memory_special_shm(size_t size, size_t alignment) {
ASSERT_TRUE(UseSHM) << "must be used only when UseSHM is true";
char* addr = ShmMemory::reserve_memory_special_shm(size, alignment, NULL, false);
if (addr != NULL) {
ShmMemory mr(addr, size);
EXPECT_PRED2(is_ptr_aligned, addr, alignment);
EXPECT_PRED2(is_ptr_aligned, addr, os::large_page_size());
small_page_write(addr, size);
}
}
} }
TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_aligned) { TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_aligned) {
if (!UseHugeTLBFS) { if (!using_static_hugepages()) {
return; return;
} }
size_t lp = os::large_page_size(); size_t lp = os::large_page_size();
@ -115,7 +91,7 @@ TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_aligned) {
} }
TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_not_aligned_without_addr) { TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_not_aligned_without_addr) {
if (!UseHugeTLBFS) { if (!using_static_hugepages()) {
return; return;
} }
size_t lp = os::large_page_size(); size_t lp = os::large_page_size();
@ -142,7 +118,7 @@ TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_not_aligned_without_add
} }
TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_not_aligned_with_good_req_addr) { TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_not_aligned_with_good_req_addr) {
if (!UseHugeTLBFS) { if (!using_static_hugepages()) {
return; return;
} }
size_t lp = os::large_page_size(); size_t lp = os::large_page_size();
@ -183,7 +159,7 @@ TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_not_aligned_with_good_r
TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_not_aligned_with_bad_req_addr) { TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_not_aligned_with_bad_req_addr) {
if (!UseHugeTLBFS) { if (!using_static_hugepages()) {
return; return;
} }
size_t lp = os::large_page_size(); size_t lp = os::large_page_size();
@ -233,20 +209,6 @@ TEST_VM(os_linux, reserve_memory_special_huge_tlbfs_size_not_aligned_with_bad_re
} }
} }
TEST_VM(os_linux, reserve_memory_special_shm) {
if (!UseSHM) {
return;
}
size_t lp = os::large_page_size();
size_t ag = os::vm_allocation_granularity();
for (size_t size = ag; size < lp * 3; size += ag) {
for (size_t alignment = ag; is_size_aligned(size, alignment); alignment *= 2) {
EXPECT_NO_FATAL_FAILURE(test_reserve_memory_special_shm(size, alignment));
}
}
}
class TestReserveMemorySpecial : AllStatic { class TestReserveMemorySpecial : AllStatic {
public: public:
static void small_page_write(void* addr, size_t size) { static void small_page_write(void* addr, size_t size) {
@ -259,26 +221,21 @@ class TestReserveMemorySpecial : AllStatic {
} }
static void test_reserve_memory_special_huge_tlbfs_size_aligned(size_t size, size_t alignment, size_t page_size) { static void test_reserve_memory_special_huge_tlbfs_size_aligned(size_t size, size_t alignment, size_t page_size) {
if (!UseHugeTLBFS) { if (!using_static_hugepages()) {
return; return;
} }
char* addr = os::reserve_memory_special(size, alignment, page_size, NULL, false);
char* addr = os::Linux::reserve_memory_special_huge_tlbfs(size, alignment, page_size, NULL, false);
if (addr != NULL) { if (addr != NULL) {
small_page_write(addr, size); small_page_write(addr, size);
os::release_memory_special(addr, size);
os::Linux::release_memory_special_huge_tlbfs(addr, size);
} }
} }
static void test_reserve_memory_special_huge_tlbfs_size_aligned() { static void test_reserve_memory_special_huge_tlbfs_size_aligned() {
if (!UseHugeTLBFS) { if (!using_static_hugepages()) {
return; return;
} }
size_t lp = os::large_page_size(); size_t lp = os::large_page_size();
for (size_t size = lp; size <= lp * 10; size += lp) { for (size_t size = lp; size <= lp * 10; size += lp) {
test_reserve_memory_special_huge_tlbfs_size_aligned(size, lp, lp); test_reserve_memory_special_huge_tlbfs_size_aligned(size, lp, lp);
} }
@ -324,11 +281,11 @@ class TestReserveMemorySpecial : AllStatic {
for (int i = 0; i < num_sizes; i++) { for (int i = 0; i < num_sizes; i++) {
const size_t size = sizes[i]; const size_t size = sizes[i];
for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) { for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
char* p = os::Linux::reserve_memory_special_huge_tlbfs(size, alignment, lp, NULL, false); char* p = os::reserve_memory_special(size, alignment, lp, NULL, false);
if (p != NULL) { if (p != NULL) {
EXPECT_TRUE(is_aligned(p, alignment)); EXPECT_TRUE(is_aligned(p, alignment));
small_page_write(p, size); small_page_write(p, size);
os::Linux::release_memory_special_huge_tlbfs(p, size); os::release_memory_special(p, size);
} }
} }
} }
@ -339,11 +296,11 @@ class TestReserveMemorySpecial : AllStatic {
for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) { for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
// req_addr must be at least large page aligned. // req_addr must be at least large page aligned.
char* const req_addr = align_up(mapping1, MAX2(alignment, lp)); char* const req_addr = align_up(mapping1, MAX2(alignment, lp));
char* p = os::Linux::reserve_memory_special_huge_tlbfs(size, alignment, lp, req_addr, false); char* p = os::reserve_memory_special(size, alignment, lp, req_addr, false);
if (p != NULL) { if (p != NULL) {
EXPECT_EQ(p, req_addr); EXPECT_EQ(p, req_addr);
small_page_write(p, size); small_page_write(p, size);
os::Linux::release_memory_special_huge_tlbfs(p, size); os::release_memory_special(p, size);
} }
} }
} }
@ -354,7 +311,7 @@ class TestReserveMemorySpecial : AllStatic {
for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) { for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
// req_addr must be at least large page aligned. // req_addr must be at least large page aligned.
char* const req_addr = align_up(mapping2, MAX2(alignment, lp)); char* const req_addr = align_up(mapping2, MAX2(alignment, lp));
char* p = os::Linux::reserve_memory_special_huge_tlbfs(size, alignment, lp, req_addr, false); char* p = os::reserve_memory_special(size, alignment, lp, req_addr, false);
// as the area around req_addr contains already existing mappings, the API should always // as the area around req_addr contains already existing mappings, the API should always
// return NULL (as per contract, it cannot return another address) // return NULL (as per contract, it cannot return another address)
EXPECT_TRUE(p == NULL); EXPECT_TRUE(p == NULL);
@ -365,47 +322,13 @@ class TestReserveMemorySpecial : AllStatic {
} }
static void test_reserve_memory_special_huge_tlbfs() { static void test() {
if (!UseHugeTLBFS) { if (!using_static_hugepages()) {
return; return;
} }
test_reserve_memory_special_huge_tlbfs_size_aligned(); test_reserve_memory_special_huge_tlbfs_size_aligned();
test_reserve_memory_special_huge_tlbfs_size_not_aligned(); test_reserve_memory_special_huge_tlbfs_size_not_aligned();
} }
static void test_reserve_memory_special_shm(size_t size, size_t alignment) {
if (!UseSHM) {
return;
}
char* addr = os::Linux::reserve_memory_special_shm(size, alignment, NULL, false);
if (addr != NULL) {
EXPECT_TRUE(is_aligned(addr, alignment));
EXPECT_TRUE(is_aligned(addr, os::large_page_size()));
small_page_write(addr, size);
os::Linux::release_memory_special_shm(addr, size);
}
}
static void test_reserve_memory_special_shm() {
size_t lp = os::large_page_size();
size_t ag = os::vm_allocation_granularity();
for (size_t size = ag; size < lp * 3; size += ag) {
for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
test_reserve_memory_special_shm(size, alignment);
}
}
}
static void test() {
test_reserve_memory_special_huge_tlbfs();
test_reserve_memory_special_shm();
}
}; };
TEST_VM(os_linux, reserve_memory_special) { TEST_VM(os_linux, reserve_memory_special) {

View File

@ -35,7 +35,7 @@ package gc.arguments;
* @modules java.management/sun.management * @modules java.management/sun.management
* @build TestSmallInitialHeapWithLargePageAndNUMA * @build TestSmallInitialHeapWithLargePageAndNUMA
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UseHugeTLBFS -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI gc.arguments.TestSmallInitialHeapWithLargePageAndNUMA * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI gc.arguments.TestSmallInitialHeapWithLargePageAndNUMA
*/ */
import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.OutputAnalyzer;
@ -65,7 +65,6 @@ public class TestSmallInitialHeapWithLargePageAndNUMA {
"-Xms" + String.valueOf(initHeap), "-Xms" + String.valueOf(initHeap),
"-Xmx" + String.valueOf(maxHeap), "-Xmx" + String.valueOf(maxHeap),
"-XX:+UseNUMA", "-XX:+UseNUMA",
"-XX:+UseHugeTLBFS",
"-XX:+PrintFlagsFinal", "-XX:+PrintFlagsFinal",
"-version"); "-version");
OutputAnalyzer analyzer = new OutputAnalyzer(pb_enabled.start()); OutputAnalyzer analyzer = new OutputAnalyzer(pb_enabled.start());

View File

@ -55,13 +55,3 @@
* @requires vm.flagless * @requires vm.flagless
* @run main/native GTestWrapper --gtest_filter=os* -XX:-PrintWarnings -XX:+UseLargePages -XX:LargePageSizeInBytes=1G * @run main/native GTestWrapper --gtest_filter=os* -XX:-PrintWarnings -XX:+UseLargePages -XX:LargePageSizeInBytes=1G
*/ */
/* @test id=use-large-pages-sysV
* @summary Run metaspace-related gtests for reclaim policy none (with verifications)
* @requires os.family == "linux"
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.xml
* @requires vm.flagless
* @run main/native GTestWrapper --gtest_filter=os* -XX:-PrintWarnings -XX:+UseLargePages -XX:+UseSHM
*/

View File

@ -43,9 +43,6 @@ public class TestLargePagesFlags {
public static void main(String [] args) throws Exception { public static void main(String [] args) throws Exception {
testUseTransparentHugePages(); testUseTransparentHugePages();
testUseHugeTLBFS();
testUseSHM();
testCombinations();
} }
public static void testUseTransparentHugePages() throws Exception { public static void testUseTransparentHugePages() throws Exception {
@ -60,27 +57,21 @@ public class TestLargePagesFlags {
UseTransparentHugePages(true)) UseTransparentHugePages(true))
.expect( .expect(
UseLargePages(false), UseLargePages(false),
UseTransparentHugePages(false), UseTransparentHugePages(false));
UseHugeTLBFS(false),
UseSHM(false));
// Explicitly turn on UseTransparentHugePages. // Explicitly turn on UseTransparentHugePages.
new FlagTester() new FlagTester()
.use(UseTransparentHugePages(true)) .use(UseTransparentHugePages(true))
.expect( .expect(
UseLargePages(true), UseLargePages(true),
UseTransparentHugePages(true), UseTransparentHugePages(true));
UseHugeTLBFS(false),
UseSHM(false));
new FlagTester() new FlagTester()
.use(UseLargePages(true), .use(UseLargePages(true),
UseTransparentHugePages(true)) UseTransparentHugePages(true))
.expect( .expect(
UseLargePages(true), UseLargePages(true),
UseTransparentHugePages(true), UseTransparentHugePages(true));
UseHugeTLBFS(false),
UseSHM(false));
// Setting a specific large pages flag will turn // Setting a specific large pages flag will turn
// off heuristics to choose large pages type. // off heuristics to choose large pages type.
@ -89,9 +80,7 @@ public class TestLargePagesFlags {
UseTransparentHugePages(false)) UseTransparentHugePages(false))
.expect( .expect(
UseLargePages(false), UseLargePages(false),
UseTransparentHugePages(false), UseTransparentHugePages(false));
UseHugeTLBFS(false),
UseSHM(false));
// Don't turn on UseTransparentHugePages // Don't turn on UseTransparentHugePages
// unless the user explicitly asks for them. // unless the user explicitly asks for them.
@ -101,192 +90,6 @@ public class TestLargePagesFlags {
UseTransparentHugePages(false)); UseTransparentHugePages(false));
} }
public static void testUseHugeTLBFS() throws Exception {
if (!canUse(UseHugeTLBFS(true))) {
System.out.println("Skipping testUseHugeTLBFS");
return;
}
// -XX:-UseLargePages overrides all other flags.
new FlagTester()
.use(UseLargePages(false),
UseHugeTLBFS(true))
.expect(
UseLargePages(false),
UseTransparentHugePages(false),
UseHugeTLBFS(false),
UseSHM(false));
// Explicitly turn on UseHugeTLBFS.
new FlagTester()
.use(UseHugeTLBFS(true))
.expect(
UseLargePages(true),
UseTransparentHugePages(false),
UseHugeTLBFS(true),
UseSHM(false));
new FlagTester()
.use(UseLargePages(true),
UseHugeTLBFS(true))
.expect(
UseLargePages(true),
UseTransparentHugePages(false),
UseHugeTLBFS(true),
UseSHM(false));
// Setting a specific large pages flag will turn
// off heuristics to choose large pages type.
new FlagTester()
.use(UseLargePages(true),
UseHugeTLBFS(false))
.expect(
UseLargePages(false),
UseTransparentHugePages(false),
UseHugeTLBFS(false),
UseSHM(false));
// Using UseLargePages will default to UseHugeTLBFS large pages.
new FlagTester()
.use(UseLargePages(true))
.expect(
UseLargePages(true),
UseTransparentHugePages(false),
UseHugeTLBFS(true),
UseSHM(false));
}
public static void testUseSHM() throws Exception {
if (!canUse(UseSHM(true))) {
System.out.println("Skipping testUseSHM");
return;
}
// -XX:-UseLargePages overrides all other flags.
new FlagTester()
.use(UseLargePages(false),
UseSHM(true))
.expect(
UseLargePages(false),
UseTransparentHugePages(false),
UseHugeTLBFS(false),
UseSHM(false));
// Explicitly turn on UseSHM.
new FlagTester()
.use(UseSHM(true))
.expect(
UseLargePages(true),
UseTransparentHugePages(false),
UseHugeTLBFS(false),
UseSHM(true)) ;
new FlagTester()
.use(UseLargePages(true),
UseSHM(true))
.expect(
UseLargePages(true),
UseTransparentHugePages(false),
UseHugeTLBFS(false),
UseSHM(true)) ;
// Setting a specific large pages flag will turn
// off heuristics to choose large pages type.
new FlagTester()
.use(UseLargePages(true),
UseSHM(false))
.expect(
UseLargePages(false),
UseTransparentHugePages(false),
UseHugeTLBFS(false),
UseSHM(false));
// Setting UseLargePages can allow the system to choose
// UseHugeTLBFS instead of UseSHM, but never UseTransparentHugePages.
new FlagTester()
.use(UseLargePages(true))
.expect(
UseLargePages(true),
UseTransparentHugePages(false));
}
public static void testCombinations() throws Exception {
if (!canUse(UseSHM(true)) || !canUse(UseHugeTLBFS(true))) {
System.out.println("Skipping testUseHugeTLBFSAndUseSHMCombination");
return;
}
// UseHugeTLBFS takes precedence over SHM.
new FlagTester()
.use(UseLargePages(true),
UseHugeTLBFS(true),
UseSHM(true))
.expect(
UseLargePages(true),
UseTransparentHugePages(false),
UseHugeTLBFS(true),
UseSHM(false));
new FlagTester()
.use(UseLargePages(true),
UseHugeTLBFS(false),
UseSHM(true))
.expect(
UseLargePages(true),
UseTransparentHugePages(false),
UseHugeTLBFS(false),
UseSHM(true));
new FlagTester()
.use(UseLargePages(true),
UseHugeTLBFS(true),
UseSHM(false))
.expect(
UseLargePages(true),
UseTransparentHugePages(false),
UseHugeTLBFS(true),
UseSHM(false));
new FlagTester()
.use(UseLargePages(true),
UseHugeTLBFS(false),
UseSHM(false))
.expect(
UseLargePages(false),
UseTransparentHugePages(false),
UseHugeTLBFS(false),
UseSHM(false));
if (!canUse(UseTransparentHugePages(true))) {
return;
}
// UseTransparentHugePages takes precedence.
new FlagTester()
.use(UseLargePages(true),
UseTransparentHugePages(true),
UseHugeTLBFS(true),
UseSHM(true))
.expect(
UseLargePages(true),
UseTransparentHugePages(true),
UseHugeTLBFS(false),
UseSHM(false));
new FlagTester()
.use(UseTransparentHugePages(true),
UseHugeTLBFS(true),
UseSHM(true))
.expect(
UseLargePages(true),
UseTransparentHugePages(true),
UseHugeTLBFS(false),
UseSHM(false));
}
private static class FlagTester { private static class FlagTester {
private Flag [] useFlags; private Flag [] useFlags;
@ -304,6 +107,7 @@ public class TestLargePagesFlags {
System.out.println("Expecting: " + Arrays.toString(expectedFlags)); System.out.println("Expecting: " + Arrays.toString(expectedFlags));
OutputAnalyzer output = executeNewJVM(useFlags); OutputAnalyzer output = executeNewJVM(useFlags);
output.reportDiagnosticSummary();
for (Flag flag : expectedFlags) { for (Flag flag : expectedFlags) {
System.out.println("Looking for: " + flag.flagString()); System.out.println("Looking for: " + flag.flagString());
@ -329,7 +133,7 @@ public class TestLargePagesFlags {
for (Flag flag : flags) { for (Flag flag : flags) {
args.add(flag.flagString()); args.add(flag.flagString());
} }
args.add("-XX:+PrintFlagsFinal"); args.add("-Xlog:pagesize");
args.add("-version"); args.add("-version");
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args); ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
@ -357,14 +161,6 @@ public class TestLargePagesFlags {
return new BooleanFlag("UseTransparentHugePages", value); return new BooleanFlag("UseTransparentHugePages", value);
} }
private static Flag UseHugeTLBFS(boolean value) {
return new BooleanFlag("UseHugeTLBFS", value);
}
private static Flag UseSHM(boolean value) {
return new BooleanFlag("UseSHM", value);
}
private static class BooleanFlag implements Flag { private static class BooleanFlag implements Flag {
private String name; private String name;
private boolean value; private boolean value;