8369811: ZGC: Robust NUMA configuration detection

Co-authored-by: Axel Boldt-Christmas <aboldtch@openjdk.org>
Reviewed-by: aboldtch, sjohanss
This commit is contained in:
Joel Sikström 2025-10-20 10:29:21 +00:00
parent ee353201d1
commit 73923601d8
6 changed files with 49 additions and 9 deletions

View File

@ -46,3 +46,7 @@ uint32_t ZNUMA::memory_id(uintptr_t addr) {
// NUMA support not enabled, assume everything belongs to node zero
return 0;
}
int ZNUMA::numa_id_to_node(uint32_t numa_id) {
ShouldNotCallThis();
}

View File

@ -32,12 +32,35 @@
#include "runtime/os.hpp"
#include "utilities/debug.hpp"
static uint* z_numa_id_to_node = nullptr;
static uint32_t* z_node_to_numa_id = nullptr;
void ZNUMA::pd_initialize() {
_enabled = UseNUMA;
size_t configured_nodes = 0;
if (UseNUMA) {
const size_t max_nodes = os::Linux::numa_num_configured_nodes();
z_numa_id_to_node = NEW_C_HEAP_ARRAY(uint, max_nodes, mtGC);
configured_nodes = os::numa_get_leaf_groups(z_numa_id_to_node, 0);
z_node_to_numa_id = NEW_C_HEAP_ARRAY(uint32_t, max_nodes, mtGC);
// Fill the array with invalid NUMA ids
for (uint32_t i = 0; i < max_nodes; i++) {
z_node_to_numa_id[i] = (uint32_t)-1;
}
// Fill the reverse mappings
for (uint32_t i = 0; i < configured_nodes; i++) {
z_node_to_numa_id[z_numa_id_to_node[i]] = i;
}
}
// UseNUMA and is_faked() are mutually excluded in zArguments.cpp.
_count = UseNUMA
? os::Linux::numa_max_node() + 1
? configured_nodes
: !FLAG_IS_DEFAULT(ZFakeNUMA)
? ZFakeNUMA
: 1; // No NUMA nodes
@ -54,7 +77,7 @@ uint32_t ZNUMA::id() {
return 0;
}
return os::Linux::get_node_by_cpu(ZCPU::id());
return z_node_to_numa_id[os::Linux::get_node_by_cpu(ZCPU::id())];
}
uint32_t ZNUMA::memory_id(uintptr_t addr) {
@ -63,14 +86,21 @@ uint32_t ZNUMA::memory_id(uintptr_t addr) {
return 0;
}
uint32_t id = (uint32_t)-1;
int node = -1;
if (ZSyscall::get_mempolicy((int*)&id, nullptr, 0, (void*)addr, MPOL_F_NODE | MPOL_F_ADDR) == -1) {
if (ZSyscall::get_mempolicy(&node, nullptr, 0, (void*)addr, MPOL_F_NODE | MPOL_F_ADDR) == -1) {
ZErrno err;
fatal("Failed to get NUMA id for memory at " PTR_FORMAT " (%s)", addr, err.to_string());
}
assert(id < _count, "Invalid NUMA id");
DEBUG_ONLY(const int max_nodes = os::Linux::numa_num_configured_nodes();)
assert(node < max_nodes, "NUMA node is out of bounds node=%d, max=%d", node, max_nodes);
return id;
return z_node_to_numa_id[node];
}
int ZNUMA::numa_id_to_node(uint32_t numa_id) {
assert(numa_id < _count, "NUMA id out of range 0 <= %ud <= %ud", numa_id, _count);
return (int)z_numa_id_to_node[numa_id];
}

View File

@ -629,7 +629,7 @@ retry:
size_t ZPhysicalMemoryBacking::commit_numa_preferred(zbacking_offset offset, size_t length, uint32_t numa_id) const {
// Setup NUMA policy to allocate memory from a preferred node
os::Linux::numa_set_preferred((int)numa_id);
os::Linux::numa_set_preferred(ZNUMA::numa_id_to_node(numa_id));
const size_t committed = commit_default(offset, length);

View File

@ -46,3 +46,7 @@ uint32_t ZNUMA::memory_id(uintptr_t addr) {
// NUMA support not enabled, assume everything belongs to node zero
return 0;
}
int ZNUMA::numa_id_to_node(uint32_t numa_id) {
ShouldNotCallThis();
}

View File

@ -53,6 +53,8 @@ public:
static size_t calculate_share(uint32_t numa_id, size_t total, size_t granule = ZGranuleSize, uint32_t ignore_count = 0);
static const char* to_string();
static int numa_id_to_node(uint32_t numa_id);
};
#endif // SHARE_GC_Z_ZNUMA_HPP

View File

@ -108,7 +108,7 @@ void ZPhysicalMemoryManager::try_enable_uncommit(size_t min_capacity, size_t max
// Test if uncommit is supported by the operating system by committing
// and then uncommitting a granule.
const ZVirtualMemory vmem(zoffset(0), ZGranuleSize);
if (!commit(vmem, (uint32_t)-1) || !uncommit(vmem)) {
if (!commit(vmem, 0) || !uncommit(vmem)) {
log_info_p(gc, init)("Uncommit: Implicitly Disabled (Not supported by operating system)");
FLAG_SET_ERGO(ZUncommit, false);
return;
@ -293,7 +293,7 @@ void ZPhysicalMemoryManager::map(const ZVirtualMemory& vmem, uint32_t numa_id) c
// Setup NUMA preferred for large pages
if (ZNUMA::is_enabled() && ZLargePages::is_explicit()) {
os::numa_make_local((char*)addr, size, (int)numa_id);
os::numa_make_local((char*)addr, size, ZNUMA::numa_id_to_node(numa_id));
}
}