RFR: 8252500: ZGC on aarch64: Unable to allocate heap for certain Linux kernel configurations
Stefan Karlsson
stefank at openjdk.java.net
Mon Sep 7 09:35:07 UTC 2020
On Mon, 7 Sep 2020 07:27:05 GMT, Christoph Göttschkes <cgo at openjdk.org> wrote:
> The patch introduces a new function to probe for the highest valid bit in the virtual address space for userspace
> programs on Linux.
> I guarded the whole implementation to only probe on Linux, other platforms will remain unaffected. Possibly, it would
> be nicer to move the probing code into an OS+ARCH specific source file. But since this is only a single function, I
> thought it would be better to put it right next to the caller and guard it with an #ifdef LINUX. The probing mechanism
> uses a combination of msync + mmap, to first check if the address is valid using msync (if msync succeeds, the address
> was valid). If msync fails, mmap is used to check if msync failed because the memory wasn't mapped, or if it failed
> because the address is invalid. Due to some undefined behavior (documented in the msync man page), I also use a single
> mmap at the end, if the msync approach failed before. I tested msync with different combinations of mappings, and also
> with sbrk, and it always succeeded, or failed with ENOMEM. I never got back any other error code. The specified
> minimum value has been chosen "randomly". The JVM terminates (unable to allocate heap), if this minimum value is
> smaller than the requested Java Heap size, so it might be better to make the minimum dependent on the MaxHeapSize and
> not a compile time constant? I didn't want to make the minimum too big, since for aarch64 on Linux, the documented
> minimum would be 38 (see [1]). I avoided MAP_FIXED_NOREPLACE, because according to the man page, it has been added in
> Linux 4.17. There are still plenty of stable kernel versions around which will not have that feature, which means we
> need to implement a workaround for it. Some of my test devices also have a kernel version lower than that. I executed
> the HotSpot tier1 JTreg tests on two different aarch64 devices. One with 4KB pages and 3 page levels and the other with
> 4KB pages and 4 page levels. Tests passed on both devices. [1]
> https://www.kernel.org/doc/Documentation/arm64/memory.txt
src/hotspot/cpu/aarch64/gc/z/zGlobals_aarch64.cpp line 183:
> 181: void* result_addr = mmap((void*) high_addr, page_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1,
> 0); 182: if (result_addr != MAP_FAILED) {
> 183: max_address_bit = BitsPerSize_t - count_leading_zeros((size_t) result_addr) - 1;
It's not obvious to me that the '- 1' is correct here.
src/hotspot/cpu/aarch64/gc/z/zGlobals_aarch64.cpp line 150:
> 148: size_t max_address_bit = 0;
> 149: const size_t page_size = os::vm_page_size();
> 150: for (int i = DEFAULT_MAX_ADDRESS_BIT; i > MINIMUM_MAX_ADDRESS_BIT && max_address_bit == 0; --i) {
There's a bit of a mismatch between the type of 'i' and 'max_address_bit'. See also 'BitsPerSize_t -
count_leading_zeros((size_t) result_addr) - 1;'. I think that changing max_address_bit to be an int, and getting rid of
the size_t's here will fix that.
-------------
PR: https://git.openjdk.java.net/jdk/pull/40
More information about the hotspot-gc-dev
mailing list