Skip to content

Commit 73ba3ae

Browse files
mychrispliden
authored andcommitted
8252500: ZGC on aarch64: Unable to allocate heap for certain Linux kernel configurations
Reviewed-by: stefank, eosterlund, pliden
1 parent 5dd1ead commit 73ba3ae

File tree

1 file changed

+63
-2
lines changed

1 file changed

+63
-2
lines changed

src/hotspot/cpu/aarch64/gc/z/zGlobals_aarch64.cpp

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,17 @@
2222
*/
2323

2424
#include "precompiled.hpp"
25+
#include "gc/shared/gcLogPrecious.hpp"
2526
#include "gc/z/zGlobals.hpp"
2627
#include "runtime/globals.hpp"
28+
#include "runtime/os.hpp"
2729
#include "utilities/globalDefinitions.hpp"
2830
#include "utilities/powerOfTwo.hpp"
2931

32+
#ifdef LINUX
33+
#include <sys/mman.h>
34+
#endif // LINUX
35+
3036
//
3137
// The heap can have three different layouts, depending on the max heap size.
3238
//
@@ -135,9 +141,64 @@
135141
// * 63-48 Fixed (16-bits, always zero)
136142
//
137143

144+
// Default value if probing is not implemented for a certain platform: 128TB
145+
static const size_t DEFAULT_MAX_ADDRESS_BIT = 47;
146+
// Minimum value returned, if probing fails: 64GB
147+
static const size_t MINIMUM_MAX_ADDRESS_BIT = 36;
148+
149+
static size_t probe_valid_max_address_bit() {
150+
#ifdef LINUX
151+
size_t max_address_bit = 0;
152+
const size_t page_size = os::vm_page_size();
153+
for (size_t i = DEFAULT_MAX_ADDRESS_BIT; i > MINIMUM_MAX_ADDRESS_BIT; --i) {
154+
const uintptr_t base_addr = ((uintptr_t) 1U) << i;
155+
if (msync((void*)base_addr, page_size, MS_ASYNC) == 0) {
156+
// msync suceeded, the address is valid, and maybe even already mapped.
157+
max_address_bit = i;
158+
break;
159+
}
160+
if (errno != ENOMEM) {
161+
// Some error occured. This should never happen, but msync
162+
// has some undefined behavior, hence ignore this bit.
163+
#ifdef ASSERT
164+
fatal("Received '%s' while probing the address space for the highest valid bit", os::errno_name(errno));
165+
#else // ASSERT
166+
log_warning_p(gc)("Received '%s' while probing the address space for the highest valid bit", os::errno_name(errno));
167+
#endif // ASSERT
168+
continue;
169+
}
170+
// Since msync failed with ENOMEM, the page might not be mapped.
171+
// Try to map it, to see if the address is valid.
172+
void* const result_addr = mmap((void*) base_addr, page_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0);
173+
if (result_addr != MAP_FAILED) {
174+
munmap(result_addr, page_size);
175+
}
176+
if ((uintptr_t) result_addr == base_addr) {
177+
// address is valid
178+
max_address_bit = i;
179+
break;
180+
}
181+
}
182+
if (max_address_bit == 0) {
183+
// probing failed, allocate a very high page and take that bit as the maximum
184+
const uintptr_t high_addr = ((uintptr_t) 1U) << DEFAULT_MAX_ADDRESS_BIT;
185+
void* const result_addr = mmap((void*) high_addr, page_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0);
186+
if (result_addr != MAP_FAILED) {
187+
max_address_bit = BitsPerSize_t - count_leading_zeros((size_t) result_addr) - 1;
188+
munmap(result_addr, page_size);
189+
}
190+
}
191+
log_info_p(gc, init)("Probing address space for the highest valid bit: " SIZE_FORMAT, max_address_bit);
192+
return MAX2(max_address_bit, MINIMUM_MAX_ADDRESS_BIT);
193+
#else // LINUX
194+
return DEFAULT_MAX_ADDRESS_BIT;
195+
#endif // LINUX
196+
}
197+
138198
size_t ZPlatformAddressOffsetBits() {
139-
const size_t min_address_offset_bits = 42; // 4TB
140-
const size_t max_address_offset_bits = 44; // 16TB
199+
const static size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1;
200+
const size_t max_address_offset_bits = valid_max_address_offset_bits - 3;
201+
const size_t min_address_offset_bits = max_address_offset_bits - 2;
141202
const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio);
142203
const size_t address_offset_bits = log2_intptr(address_offset);
143204
return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits);

0 commit comments

Comments
 (0)