RFR: 8262291: Refactor reserve_memory_special_huge_tlbfs
Stefan Johansson
sjohanss at openjdk.java.net
Tue Mar 23 20:29:47 UTC 2021
On Tue, 23 Mar 2021 16:58:19 GMT, Ivan Walulya <iwalulya at openjdk.org> wrote:
>> Please review this refactoring of the hugetlbfs reservation code.
>>
>> **Summary**
>> In recent adventures in this area of the code I noticed a strange condition in `reserve_memory_special_huge_tlbfs` where we take the "mixed-mapping" route even if the size doesn't require any small pages to be used:
>> if (is_aligned(bytes, os::large_page_size()) && alignment <= os::large_page_size()) {
>> return reserve_memory_special_huge_tlbfs_only(bytes, req_addr, exec);
>> } else {
>> return reserve_memory_special_huge_tlbfs_mixed(bytes, alignment, req_addr, exec);
>> }
>>
>> The second condition here is needed because if the alignment is larger than the large page size, we needed to enforce this and can't just trust `mmap` to give us a properly aligned address. Doing this by using the mixed-function feels a bit weird and looking a bit more at this I found a way to refactor this function to avoid having the two helpers.
>>
>> Instead of only having the mixed path honor the passed down alignment, make sure that is always done. This will also have the side-effect that all large pages in a "mixed"-mapping will be at the start and then we will have a tail of small pages. This actually also ensures that we will use large pages for a mixed mapping, in the past there was a corner case where we could end up with just a head and tail of small pages and no large page in between (if the mapping was smaller than 2 large pages and there was no alignment constraint).
>>
>> **Testing**
>> Mach5 tier1-3 and a lot of local testing with different large page configurations.
>
> src/hotspot/os/linux/os_linux.cpp line 3929:
>
>> 3927: }
>> 3928:
>> 3929: char* os::Linux::reserve_and_commit_special(size_t bytes,
>
> method name `reserve_and_commit_` implicitly suggests that other methods with just `reserve_memory_` do not commit (to me).
That is a good point, I've struggled a bit with this function name. Since we actually do the reservation using the call to `anon_mmap_aligned()` maybe this one should just be called: `commit_memory_special()`
> src/hotspot/os/linux/os_linux.cpp line 3981:
>
>> 3979: // and the given alignment. The larger of the two will be used.
>> 3980: size_t required_alignment = MAX(os::large_page_size(), alignment);
>> 3981: char* const aligned_start = anon_mmap_aligned(req_addr, bytes, required_alignment);
>
> Do we need to add back the comment "// First reserve - but not commit"?
My hope was that the new comment would be sufficient, but if you think it is needed I could add that the reserved range is not committed here.
> src/hotspot/os/linux/os_linux.cpp line 3990:
>
>> 3988: char* large_mapping = reserve_and_commit_special(large_bytes, os::large_page_size(), aligned_start, exec);
>> 3989:
>> 3990: if (bytes == large_bytes) {
>
> Shouldn't we do the check `if (large_mapping == NULL) {` before this?
We could, and I thought about adding a comment here. I probably should have. The reason we don't do the explicit check it is that if `large_mapping == NULL` then NULL will be returned as expected and there is no additional work to be done if `bytes == large_bytes`.
> src/hotspot/os/linux/os_linux.cpp line 3998:
>
>> 3996: char* small_start = aligned_start + large_bytes;
>> 3997: size_t small_size = bytes - large_bytes;
>> 3998: if (large_mapping == NULL) {
>
> See comment above
I do the check here because I need the `small_start` and `small_size` values if `large_mapping == NULL` and there was additional memory reserved for small pages.
-------------
PR: https://git.openjdk.java.net/jdk/pull/3073
More information about the hotspot-dev
mailing list