-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8353637: ZGC: Discontiguous memory reservation is broken on Windows #24443
8353637: ZGC: Discontiguous memory reservation is broken on Windows #24443
Conversation
Co-authored-by: axel.boldt-christmas@oracle.com
/contributor add xmas92 |
👋 Welcome back stefank! A progress list of the required criteria for merging this PR into |
@stefank This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 40 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
@stefank Syntax:
User names can only be used for users in the census associated with this repository. For other contributors you need to supply the full name and email address. |
/contributor add @xmas92 |
@stefank |
Webrevs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
Thanks for the reviews! I've run this through most of tier1-7 testing on Windows. /integrate |
Going to push as commit 6ab1647.
Your commit was automatically rebased without conflicts. |
While working on JDK-8350441 I realized that the current Windows implementation to use placeholders for reservations are broken if we ever fallback to using the part that performs discontiguous heap reservation.
To understand this bug you first need to understand how and why we use the placeholder mechanism. From zMapper_windows.cpp:
And the way we implement this is through the callbacks in zVirtualMemory_windows.cpp:
So, we have the expectation that all memory areas in the memory manager should be covered by exactly one placeholder. We implement that by having the callbacks disabled while we initialize the reserved memory for the heap. This works as long as we get a contiguous memory reservation, and the code has various mechanisms to really try to get contiguous memory for the heap. However, if all those attempts fail, we have a fallback to reserve discontiguous memory. That mode uses interval halving to reserve exactly around the memory that is blocking use from getting a contiguous memory reservation. An example of this would be a request to reserve four "granules" (2MB), but the forth granule is already reserved:
After failing to reserve the four granules (A, B, C, D), the code will split the range into two halves (A, B) and (C, D), and try to reserve them individually. It will succeed to reserve (A, B) but not (C, D). So, the code registers (A, B) and proceeds to split (C, D) into two parts (C) and (D), and try to reserve them individually. It will succeed with (C) but fail with (D). So, the code registers (C). When (C) is registered, the code sees that (A, B) and (C) are adjacent and fuse them into one region (A, B, C). The problem is that we don't have any callbacks to also fuse the placeholders, so we are left with reservation placeholders over (A, B) and (C). Later one, when we want to use use (A, B) for the heap, the code works under the impression that we have on single placeholder over (A, B, C), so it tries to split that memory are into two placeholders (A, B) and (C). This fails with a fatal error, because Windows will refuse make this split since we already have split the placeholder.
The proposal to fix this is to first enable callbacks from the start, before the initializing memory reservation calls are made. And then to change the virtual memory manager to differentiate between the two kinds of insertion (and extraction) operations we have:
The reason why we need to separate these to is that in (1) the memory area has one placeholder that spans the provided memory area, but in (2) we the memory area has a placeholder for every 2MB granule (as described above).
So, the patch applies the 'insert' callback for the (2) areas to convert them into looking like (1), and then they both can use the same code to insert the memory into the virtual memory manager.
An opposite mechanism is used when "handing out" memory vs de-registering memory for being unreserved. Where the "handing out" operation will perform a 'remove' callback before actually handing out the memory, ensuring that the memory is covered by 2MB placeholders.
The shrink and grow operations are relieved of their previous duties to split and coalesce the 2MB placeholders and are now only tasked with splitting memory into two placeholders and combining two placeholders into one. This is handled by the 'grow' and 'shrink' callbacks.
To be able to provoke this bug we have written a small gtest, which I think has enough comments to explain what's going on and when things used to break down. The added tests uses enough high-level operations that I also had to add the support to unreserve memory, without it verification code starts to fail.
The added unreserve code also introduces calls to NMT to register the releasing of memory. This in turn is problematic because NMT doesn't support releasing a larger memory area than what we previously registered. So, we have a similar problem that we had with the placeholders that the code isn't prepared to have adjacent memory treated as a single memory area. This is going to be fixed by the on-going rewrites to NMT, but for now I've added a workaround to release memory in 2MB chunks, which is supported by the current NMT implementation.
I've moved some of the tests in test_zMapper_windows.cpp to the new test_zVirtualMemoryManager.cpp file so that we can run these tests on other platforms as well.
Progress
Issue
Reviewers
Contributors
<aboldtch@openjdk.org>
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/24443/head:pull/24443
$ git checkout pull/24443
Update a local copy of the PR:
$ git checkout pull/24443
$ git pull https://git.openjdk.org/jdk.git pull/24443/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 24443
View PR using the GUI difftool:
$ git pr show -t 24443
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/24443.diff
Using Webrev
Link to Webrev Comment