review request (S) - 8014611: reserve_and_align() assumptions
John Coomes
John.Coomes at oracle.com
Mon May 20 17:46:30 PDT 2013
Bengt Rutisson (bengt.rutisson at oracle.com) wrote:
>
> Hi John,
>
> Thanks for the extra explanation. It really helped!
>
> Some comments inline...
>
> On 5/18/13 1:30 AM, John Coomes wrote:
> > Bengt Rutisson (bengt.rutisson at oracle.com) wrote:
> >> Hi John,
> >>
> >> On 5/15/13 6:59 PM, John Coomes wrote:
> >>
> >> Please review this change for hs24:
> >>
> >> 8014611: reserve_and_align() assumptions are invalid on windows
> >>
> >> http://cr.openjdk.java.net/~jcoomes/8014611-reserve-and-align/
> >>
> >> The webrev has more info about the problem and the fix.
> >>
> >> -John
> >>
> >>
> >> I don't really understand how this fix helps the Windows issue. The problem on
> >> Windows is that if you try to release any part of a reserved region it will
> >> actually release the whole region instead of the part that you specified. Or
> >> did I miss understand the problem?
> > First, thanks for taking a look. And you understand the problem
> > correctly.
> >
> >> If that is the underlying issue then I would have expected this code in
> >> ReservedSpace::align_reserved_region():
> >>
> >> 83 if (beg_delta != 0) {
> >> 84 os::release_partial_region(addr, beg_delta);
> >> 85 }
> >> 86
> >> 87 if (end_delta != 0) {
> >> 88 char* release_addr = (char*) (s + beg_delta + required_size);
> >> 89 os::release_partial_region(release_addr, end_delta);
> >> 90 }
> >>
> >> to be:
> >>
> >> if (beg_delta != 0 && os::can_release_partial_region()) {
> >> ...
> >> }
> >>
> >> if (end_delta != 0 && os::can_release_partial_region()) {
> >> ...
> >> }
> >>
> >> And that os::release_partial_region() on Windows should be implemented as:
> >>
> >> bool os::release_partial_region(char* addr, size_t bytes) {
> >> ShouldNotReachHere();
> >> }
> >>
> >> I guess I am missing something. Can you explain in more detail why your
> >> approach solves the Windows uncommit problem?
> > The proposed fix allows os::release_partial_region() to be called on
> > windows (even though can_release_partial_region() returns false
> > there). That's because on windows, release_partial_region() calls
> > uncommit_memory() to return any pages that may have been committed to
> > back the partial region, which is allowed by the win api. As you say,
> > it can't return part of the virtual address range on windows, as can
> > be done on posix with mmap, but it can uncommit pages.
>
> Right. I missed that os::release_partial_region() on Windows only did
> uncommit.
>
> >
> > The currently implemented semantics of release_partial_region() are:
> >
> > If the o/s supports releasing part of a virtual address
> > reservation, do so using release_memory(). Otherwise (on
> > systems where the VA reservation must be released in its
> > entirety), uncommit any pages backing the partial region.
> >
> > I started out with a solution like you sketched above (with
> > release_partial_region() on windows essentially a no-op), but thought
> > that it would be more frugal to uncommit any memory that might back
> > the virtual addresses. The current code will not benefit from this,
> > but if another use of release_partial_region() is added, that code
> > might.
> >
> > Some options:
> >
> > I can add the description above as a comment if that would
> > help, and/or
> >
> > rename release_partial_region() to something that better
> > indicates the semantics (suggestions welcome), or
> >
> > make release_partial_region() a no-op on windows, with a small
> > loss in future-proofing
>
> I would like to suggest one more option:
>
> * Remove the os::release_partial_region() method
> * Always store raw_base and raw_size
> * Make ReservedSpace::release_memory() only use
> os::can_release_partial_region() to decide whether to use the raw_base
> or the "normal" base address for releasing
> * Let ReservedSpace::align_reserved_region() be implemented as:
>
>
> if (beg_delta != 0)
> if (os::can_release_partial_region()) {
> os::release_memory(addr, beg_delta);
> } else {
> os::uncommit_memory(addr, beg_delta);
> }
> }
>
> if (end_delta != 0) {
> if (os::can_release_partial_region()) {
> char* release_addr = (char*) (s + beg_delta + required_size);
> os::release_memory(release_addr, end_delta);
> } else {
> os::uncommit_memory(release_addr, end_delta);
> }
> }
>
>
> For me this is more intuitive than calling a method called
> os::release_partial_region() on platforms that answer false on
> os::can_release_partial_region().
Agreed; I myself noticed that calling release_partial_region() when
can_release_partial_region() returns false was a bit
counter-intuitive.
I looked at always saving _raw_base and _raw_size and using them
unconditionally when releasing memory. I'd have to save them after
every call to reserve_memory() or release_memory(), which is about a
dozen places (including in the code snippets above, where I have to
save the raw values only if can_release_partial_region() returns
true). So the first snippet above would have to be:
if (beg_delta != 0)
if (os::can_release_partial_region()) {
os::release_memory(addr, beg_delta);
save_raw_base_and_size(addr + beg_delta, size - beg_delta);
} else {
os::uncommit_memory(addr, beg_delta);
}
}
Similarly for the second snippet. And when releasing memory, I'd
still want to check that _raw_base != NULL before using it. It
started to get a bit ugly saving the values everywhere.
So I tried my second alternative (renaming release_partial_region()),
and was able to move the method from platform-dependent code into
os.cpp. It's simpler than always using _raw_base, let me know what
you think. Here's a webrev of just the rename (i.e., relative to my
original change):
http://cr.openjdk.java.net/~jcoomes/8014611-rename/
Here's a combined webrev (relative to unmodified hs24):
http://cr.openjdk.java.net/~jcoomes/8014611-combo/
-John
More information about the hotspot-runtime-dev
mailing list