mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 06:14:49 +02:00
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
Detect mmap() commit failures in Linux and Solaris os::commit_memory() impls and call vm_exit_out_of_memory(). Add os::commit_memory_or_exit(). Also tidy up some NMT accounting and some mmap() return value checking. Reviewed-by: zgu, stefank, dholmes, dsamersoff
This commit is contained in:
parent
718f3252f6
commit
72a51a0c44
18 changed files with 357 additions and 80 deletions
|
@ -2612,11 +2612,49 @@ void linux_wrap_code(char* base, size_t size) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool recoverable_mmap_error(int err) {
|
||||
// See if the error is one we can let the caller handle. This
|
||||
// list of errno values comes from JBS-6843484. I can't find a
|
||||
// Linux man page that documents this specific set of errno
|
||||
// values so while this list currently matches Solaris, it may
|
||||
// change as we gain experience with this failure mode.
|
||||
switch (err) {
|
||||
case EBADF:
|
||||
case EINVAL:
|
||||
case ENOTSUP:
|
||||
// let the caller deal with these errors
|
||||
return true;
|
||||
|
||||
default:
|
||||
// Any remaining errors on this OS can cause our reserved mapping
|
||||
// to be lost. That can cause confusion where different data
|
||||
// structures think they have the same memory mapped. The worst
|
||||
// scenario is if both the VM and a library think they have the
|
||||
// same memory mapped.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void warn_fail_commit_memory(char* addr, size_t size, bool exec,
|
||||
int err) {
|
||||
warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
|
||||
", %d) failed; error='%s' (errno=%d)", addr, size, exec,
|
||||
strerror(err), err);
|
||||
}
|
||||
|
||||
static void warn_fail_commit_memory(char* addr, size_t size,
|
||||
size_t alignment_hint, bool exec,
|
||||
int err) {
|
||||
warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
|
||||
", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", addr, size,
|
||||
alignment_hint, exec, strerror(err), err);
|
||||
}
|
||||
|
||||
// NOTE: Linux kernel does not really reserve the pages for us.
|
||||
// All it does is to check if there are enough free pages
|
||||
// left at the time of mmap(). This could be a potential
|
||||
// problem.
|
||||
bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
|
||||
int os::Linux::commit_memory_impl(char* addr, size_t size, bool exec) {
|
||||
int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
|
||||
uintptr_t res = (uintptr_t) ::mmap(addr, size, prot,
|
||||
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
|
||||
|
@ -2624,9 +2662,32 @@ bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
|
|||
if (UseNUMAInterleaving) {
|
||||
numa_make_global(addr, size);
|
||||
}
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int err = errno; // save errno from mmap() call above
|
||||
|
||||
if (!recoverable_mmap_error(err)) {
|
||||
warn_fail_commit_memory(addr, size, exec, err);
|
||||
vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "committing reserved memory.");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
|
||||
return os::Linux::commit_memory_impl(addr, size, exec) == 0;
|
||||
}
|
||||
|
||||
void os::pd_commit_memory_or_exit(char* addr, size_t size, bool exec,
|
||||
const char* mesg) {
|
||||
assert(mesg != NULL, "mesg must be specified");
|
||||
int err = os::Linux::commit_memory_impl(addr, size, exec);
|
||||
if (err != 0) {
|
||||
// the caller wants all commit errors to exit with the specified mesg:
|
||||
warn_fail_commit_memory(addr, size, exec, err);
|
||||
vm_exit_out_of_memory(size, OOM_MMAP_ERROR, mesg);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Define MAP_HUGETLB here so we can build HotSpot on old systems.
|
||||
|
@ -2639,8 +2700,9 @@ bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
|
|||
#define MADV_HUGEPAGE 14
|
||||
#endif
|
||||
|
||||
bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint,
|
||||
bool exec) {
|
||||
int os::Linux::commit_memory_impl(char* addr, size_t size,
|
||||
size_t alignment_hint, bool exec) {
|
||||
int err;
|
||||
if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) {
|
||||
int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
|
||||
uintptr_t res =
|
||||
|
@ -2651,16 +2713,46 @@ bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint,
|
|||
if (UseNUMAInterleaving) {
|
||||
numa_make_global(addr, size);
|
||||
}
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = errno; // save errno from mmap() call above
|
||||
|
||||
if (!recoverable_mmap_error(err)) {
|
||||
// However, it is not clear that this loss of our reserved mapping
|
||||
// happens with large pages on Linux or that we cannot recover
|
||||
// from the loss. For now, we just issue a warning and we don't
|
||||
// call vm_exit_out_of_memory(). This issue is being tracked by
|
||||
// JBS-8007074.
|
||||
warn_fail_commit_memory(addr, size, alignment_hint, exec, err);
|
||||
// vm_exit_out_of_memory(size, OOM_MMAP_ERROR,
|
||||
// "committing reserved memory.");
|
||||
}
|
||||
// Fall through and try to use small pages
|
||||
}
|
||||
|
||||
if (commit_memory(addr, size, exec)) {
|
||||
err = os::Linux::commit_memory_impl(addr, size, exec);
|
||||
if (err == 0) {
|
||||
realign_memory(addr, size, alignment_hint);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return err;
|
||||
}
|
||||
|
||||
bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint,
|
||||
bool exec) {
|
||||
return os::Linux::commit_memory_impl(addr, size, alignment_hint, exec) == 0;
|
||||
}
|
||||
|
||||
void os::pd_commit_memory_or_exit(char* addr, size_t size,
|
||||
size_t alignment_hint, bool exec,
|
||||
const char* mesg) {
|
||||
assert(mesg != NULL, "mesg must be specified");
|
||||
int err = os::Linux::commit_memory_impl(addr, size, alignment_hint, exec);
|
||||
if (err != 0) {
|
||||
// the caller wants all commit errors to exit with the specified mesg:
|
||||
warn_fail_commit_memory(addr, size, alignment_hint, exec, err);
|
||||
vm_exit_out_of_memory(size, OOM_MMAP_ERROR, mesg);
|
||||
}
|
||||
}
|
||||
|
||||
void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
|
||||
|
@ -2678,7 +2770,7 @@ void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) {
|
|||
// small pages on top of the SHM segment. This method always works for small pages, so we
|
||||
// allow that in any case.
|
||||
if (alignment_hint <= (size_t)os::vm_page_size() || !UseSHM) {
|
||||
commit_memory(addr, bytes, alignment_hint, false);
|
||||
commit_memory(addr, bytes, alignment_hint, !ExecMem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2931,7 +3023,7 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
|
|||
::munmap((void*)stack_extent, (uintptr_t)addr - stack_extent);
|
||||
}
|
||||
|
||||
return os::commit_memory(addr, size);
|
||||
return os::commit_memory(addr, size, !ExecMem);
|
||||
}
|
||||
|
||||
// If this is a growable mapping, remove the guard pages entirely by
|
||||
|
@ -3053,7 +3145,7 @@ bool os::Linux::hugetlbfs_sanity_check(bool warn, size_t page_size) {
|
|||
MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB,
|
||||
-1, 0);
|
||||
|
||||
if (p != (void *) -1) {
|
||||
if (p != MAP_FAILED) {
|
||||
// We don't know if this really is a huge page or not.
|
||||
FILE *fp = fopen("/proc/self/maps", "r");
|
||||
if (fp) {
|
||||
|
@ -4393,7 +4485,7 @@ jint os::init_2(void)
|
|||
|
||||
if (!UseMembar) {
|
||||
address mem_serialize_page = (address) ::mmap(NULL, Linux::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
guarantee( mem_serialize_page != NULL, "mmap Failed for memory serialize page");
|
||||
guarantee( mem_serialize_page != MAP_FAILED, "mmap Failed for memory serialize page");
|
||||
os::set_memory_serialize_page( mem_serialize_page );
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue