8340420: ZGC: Should call vm_shutdown_during_initialization if initialization fails

Reviewed-by: stefank, mli
This commit is contained in:
Axel Boldt-Christmas 2024-10-01 11:33:11 +00:00
parent 2dc3b1a71f
commit f7c7958f00
9 changed files with 117 additions and 27 deletions

View File

@ -22,10 +22,10 @@
*/
#include "precompiled.hpp"
#include "gc/shared/gcLogPrecious.hpp"
#include "gc/z/zAddress.inline.hpp"
#include "gc/z/zErrno.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zInitialize.hpp"
#include "gc/z/zLargePages.inline.hpp"
#include "gc/z/zPhysicalMemory.inline.hpp"
#include "gc/z/zPhysicalMemoryBacking_bsd.hpp"
@ -82,7 +82,7 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity)
_base = (uintptr_t)os::reserve_memory(max_capacity);
if (_base == 0) {
// Failed
log_error_pd(gc)("Failed to reserve address space for backing memory");
ZInitialize::error("Failed to reserve address space for backing memory");
return;
}

View File

@ -27,6 +27,7 @@
#include "gc/z/zArray.inline.hpp"
#include "gc/z/zErrno.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zInitialize.hpp"
#include "gc/z/zLargePages.inline.hpp"
#include "gc/z/zMountPoint_linux.hpp"
#include "gc/z/zNUMA.inline.hpp"
@ -129,6 +130,7 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity)
// Create backing file
_fd = create_fd(ZFILENAME_HEAP);
if (_fd == -1) {
ZInitialize::error("Failed to create heap backing file");
return;
}
@ -136,7 +138,7 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity)
while (ftruncate(_fd, max_capacity) == -1) {
if (errno != EINTR) {
ZErrno err;
log_error_p(gc)("Failed to truncate backing file (%s)", err.to_string());
ZInitialize::error("Failed to truncate backing file (%s)", err.to_string());
return;
}
}
@ -145,7 +147,7 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity)
struct statfs buf;
if (fstatfs(_fd, &buf) == -1) {
ZErrno err;
log_error_p(gc)("Failed to determine filesystem type for backing file (%s)", err.to_string());
ZInitialize::error("Failed to determine filesystem type for backing file (%s)", err.to_string());
return;
}
@ -158,39 +160,39 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity)
// Make sure the filesystem type matches requested large page type
if (ZLargePages::is_transparent() && !is_tmpfs()) {
log_error_p(gc)("-XX:+UseTransparentHugePages can only be enabled when using a %s filesystem",
ZFILESYSTEM_TMPFS);
ZInitialize::error("-XX:+UseTransparentHugePages can only be enabled when using a %s filesystem",
ZFILESYSTEM_TMPFS);
return;
}
if (ZLargePages::is_transparent() && !tmpfs_supports_transparent_huge_pages()) {
log_error_p(gc)("-XX:+UseTransparentHugePages on a %s filesystem not supported by kernel",
ZFILESYSTEM_TMPFS);
ZInitialize::error("-XX:+UseTransparentHugePages on a %s filesystem not supported by kernel",
ZFILESYSTEM_TMPFS);
return;
}
if (ZLargePages::is_explicit() && !is_hugetlbfs()) {
log_error_p(gc)("-XX:+UseLargePages (without -XX:+UseTransparentHugePages) can only be enabled "
"when using a %s filesystem", ZFILESYSTEM_HUGETLBFS);
ZInitialize::error("-XX:+UseLargePages (without -XX:+UseTransparentHugePages) can only be enabled "
"when using a %s filesystem", ZFILESYSTEM_HUGETLBFS);
return;
}
if (!ZLargePages::is_explicit() && is_hugetlbfs()) {
log_error_p(gc)("-XX:+UseLargePages must be enabled when using a %s filesystem",
ZFILESYSTEM_HUGETLBFS);
ZInitialize::error("-XX:+UseLargePages must be enabled when using a %s filesystem",
ZFILESYSTEM_HUGETLBFS);
return;
}
// Make sure the filesystem block size is compatible
if (ZGranuleSize % _block_size != 0) {
log_error_p(gc)("Filesystem backing the heap has incompatible block size (" SIZE_FORMAT ")",
_block_size);
ZInitialize::error("Filesystem backing the heap has incompatible block size (" SIZE_FORMAT ")",
_block_size);
return;
}
if (is_hugetlbfs() && _block_size != ZGranuleSize) {
log_error_p(gc)("%s filesystem has unexpected block size " SIZE_FORMAT " (expected " SIZE_FORMAT ")",
ZFILESYSTEM_HUGETLBFS, _block_size, ZGranuleSize);
ZInitialize::error("%s filesystem has unexpected block size " SIZE_FORMAT " (expected " SIZE_FORMAT ")",
ZFILESYSTEM_HUGETLBFS, _block_size, ZGranuleSize);
return;
}

View File

@ -49,6 +49,7 @@
#include "memory/universe.hpp"
#include "oops/stackChunkOop.hpp"
#include "runtime/continuationJavaClasses.hpp"
#include "runtime/java.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/stackWatermarkSet.hpp"
#include "services/memoryUsage.hpp"
@ -60,7 +61,7 @@ ZCollectedHeap* ZCollectedHeap::heap() {
ZCollectedHeap::ZCollectedHeap()
: _barrier_set(),
_initialize(&_barrier_set),
_initializer(&_barrier_set),
_heap(),
_driver_minor(new ZDriverMinor()),
_driver_major(new ZDriverMajor()),
@ -78,11 +79,14 @@ const char* ZCollectedHeap::name() const {
jint ZCollectedHeap::initialize() {
if (!_heap.is_initialized()) {
vm_shutdown_during_initialization(ZInitialize::error_message());
return JNI_ENOMEM;
}
Universe::set_verify_data(~(ZAddressHeapBase - 1) | 0x7, ZAddressHeapBase);
ZInitialize::finish();
return JNI_OK;
}

View File

@ -43,7 +43,7 @@ class ZCollectedHeap : public CollectedHeap {
private:
ZBarrierSet _barrier_set;
ZInitialize _initialize;
ZInitializer _initializer;
ZHeap _heap;
ZDriverMinor* _driver_minor;
ZDriverMajor* _driver_major;

View File

@ -34,6 +34,7 @@
#include "gc/z/zHeap.inline.hpp"
#include "gc/z/zHeapIterator.hpp"
#include "gc/z/zHeuristics.hpp"
#include "gc/z/zInitialize.hpp"
#include "gc/z/zPage.inline.hpp"
#include "gc/z/zPageTable.inline.hpp"
#include "gc/z/zResurrection.hpp"
@ -74,7 +75,7 @@ ZHeap::ZHeap()
// Prime cache
if (!_page_allocator.prime_cache(_old.workers(), InitialHeapSize)) {
log_error_p(gc)("Failed to allocate initial Java heap (" SIZE_FORMAT "M)", InitialHeapSize / M);
ZInitialize::error("Failed to allocate initial Java heap (" SIZE_FORMAT "M)", InitialHeapSize / M);
return;
}

View File

@ -22,6 +22,7 @@
*/
#include "precompiled.hpp"
#include "gc/shared/gcLogPrecious.hpp"
#include "gc/z/zAddress.hpp"
#include "gc/z/zBarrierSet.hpp"
#include "gc/z/zCPU.hpp"
@ -38,9 +39,19 @@
#include "gc/z/zThreadLocalAllocBuffer.hpp"
#include "gc/z/zTracer.hpp"
#include "logging/log.hpp"
#include "nmt/memTag.hpp"
#include "runtime/vm_version.hpp"
#include "utilities/formatBuffer.hpp"
ZInitialize::ZInitialize(ZBarrierSet* barrier_set) {
char ZInitialize::_error_message[ErrorMessageLength] = {};
bool ZInitialize::_had_error = false;
bool ZInitialize::_finished = false;
ZInitializer::ZInitializer(ZBarrierSet* barrier_set) {
ZInitialize::initialize(barrier_set);
}
void ZInitialize::initialize(ZBarrierSet* barrier_set) {
log_info(gc, init)("Initializing %s", ZName);
log_info(gc, init)("Version: %s (%s)",
VM_Version::vm_release(),
@ -62,3 +73,51 @@ ZInitialize::ZInitialize(ZBarrierSet* barrier_set) {
pd_initialize();
}
void ZInitialize::register_error(bool debug, const char *error_msg) {
guarantee(!_finished, "Only register errors during initialization");
if (!_had_error) {
strncpy(_error_message, error_msg, ErrorMessageLength - 1);
_had_error = true;
}
if (debug) {
log_error_pd(gc)("%s", error_msg);
} else {
log_error_p(gc)("%s", error_msg);
}
}
void ZInitialize::error(const char* msg_format, ...) {
va_list argp;
va_start(argp, msg_format);
const FormatBuffer<ErrorMessageLength> error_msg(FormatBufferDummy(), msg_format, argp);
va_end(argp);
register_error(false /* debug */, error_msg);
}
void ZInitialize::error_d(const char* msg_format, ...) {
va_list argp;
va_start(argp, msg_format);
const FormatBuffer<ErrorMessageLength> error_msg(FormatBufferDummy(), msg_format, argp);
va_end(argp);
register_error(true /* debug */, error_msg);
}
bool ZInitialize::had_error() {
return _had_error;
}
const char* ZInitialize::error_message() {
assert(had_error(), "Should have registered an error");
if (had_error()) {
return _error_message;
}
return "Unknown error, check error GC logs";
}
void ZInitialize::finish() {
guarantee(!_finished, "Only finish initialization once");
_finished = true;
}

View File

@ -24,16 +24,39 @@
#ifndef SHARE_GC_Z_ZINITIALIZE_HPP
#define SHARE_GC_Z_ZINITIALIZE_HPP
#include "memory/allocation.hpp"
#include "memory/allStatic.hpp"
#include "utilities/compilerWarnings.hpp"
#include <cstddef>
class ZBarrierSet;
class ZInitialize {
class ZInitializer {
public:
ZInitializer(ZBarrierSet* barrier_set);
};
class ZInitialize : public AllStatic {
private:
void pd_initialize();
static constexpr size_t ErrorMessageLength = 256;
static char _error_message[ErrorMessageLength];
static bool _had_error;
static bool _finished;
static void register_error(bool debug, const char *error_msg);
static void pd_initialize();
public:
ZInitialize(ZBarrierSet* barrier_set);
static void error(const char* msg_format, ...) ATTRIBUTE_PRINTF(1, 2);
static void error_d(const char* msg_format, ...) ATTRIBUTE_PRINTF(1, 2);
static bool had_error();
static const char* error_message();
static void initialize(ZBarrierSet* barrier_set);
static void finish();
};
#endif // SHARE_GC_Z_ZINITIALIZE_HPP

View File

@ -22,8 +22,8 @@
*/
#include "precompiled.hpp"
#include "gc/shared/gcLogPrecious.hpp"
#include "gc/shared/gc_globals.hpp"
#include "gc/z/zInitialize.hpp"
#include "gc/z/zLock.inline.hpp"
#include "gc/z/zMarkStack.inline.hpp"
#include "gc/z/zMarkStackAllocator.hpp"
@ -43,7 +43,7 @@ ZMarkStackSpace::ZMarkStackSpace()
const size_t size = ZMarkStackSpaceLimit;
const uintptr_t addr = (uintptr_t)os::reserve_memory(size, !ExecMem, mtGC);
if (addr == 0) {
log_error_pd(gc, marking)("Failed to reserve address space for mark stacks");
ZInitialize::error_d("Failed to reserve address space for mark stacks");
return;
}

View File

@ -27,6 +27,7 @@
#include "gc/z/zAddress.inline.hpp"
#include "gc/z/zAddressSpaceLimit.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zInitialize.hpp"
#include "gc/z/zNMT.hpp"
#include "gc/z/zVirtualMemory.inline.hpp"
#include "utilities/align.hpp"
@ -44,7 +45,7 @@ ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity)
// Reserve address space
if (!reserve(max_capacity)) {
log_error_pd(gc)("Failed to reserve enough address space for Java heap");
ZInitialize::error_d("Failed to reserve enough address space for Java heap");
return;
}