review request (S) - 8014611: reserve_and_align() assumptions

Bengt Rutisson bengt.rutisson at oracle.com
Mon May 20 23:10:59 PDT 2013


On 5/21/13 2:46 AM, John Coomes wrote:
> 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.

Good point. I totally agree.

>
> 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/

Good idea! I like this much better!

Some minor comments based on the combined webrev:

In theory you don't need to save the raw_size since the size does not 
matter when you release memory on Windows. But it looks more consistent 
to do save the size too, so I think it is probably better to keep it.

In ReservedSpace::release_memory() I find this a bit hard to read:

   const bool ok = _raw_base == NULL ?
     os::release_memory(default_addr, default_size) :
     os::release_memory(_raw_base, _raw_size);

For me I think an if statement here would be faster to read.


The constructors for ReservedSpace are a mess. But it seems like all 4 
of them call ReservedSpace::initialize(), so it should be enough to have 
the call to save_raw_base_and_size(NULL, 0) in 
ReservedSpace::initialize() rather than in the constructors.

I realize that this is not 100% safe since a constructor could 
potentially call release_memory() before it calls initialize(). So, a 
safer alternative would be to initialize _raw_base and _raw_size in the 
constructors and remove the call to save_raw_base_and_size(NULL, 0) from 
initialize(). If you would like to go with that approach I would prefer 
to reset these values in an initialization list rather than with a call 
to save_raw_base_and_size(NULL, 0).


The comment for ReservedSpace::release_memory() is:

// On some systems, the address returned by os::reserve_memory() is the only
// addr that can be passed to os::release_memory().  If alignment was 
done by
// this class, that original address is _raw_base.

Would it be worth explicitly mentioning Windows here?


In both ReservedSpace::save_raw_base_and_size() and 
ReservedSpace::failed_to_reserve_as_requested() you have the return type 
on a separate line. That does not seem to be the style in the rest of 
the file.

Thanks,
Bengt

>
> -John



More information about the hotspot-runtime-dev mailing list