8261894: Remove support for UseSHM
Reviewed-by: dholmes, ayang
This commit is contained in:
parent
ad7a8e86e0
commit
c2abf120bc
@ -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") \
|
||||||
\
|
\
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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());
|
||||||
|
@ -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
|
|
||||||
*/
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user