RFR: JDK-8133706: Kitchensink hanged
Jon Masamitsu
jon.masamitsu at oracle.com
Mon Sep 28 16:43:27 UTC 2015
On 09/28/2015 01:33 AM, Bengt Rutisson wrote:
>
> Hi Jon,
>
> Thanks for looking at this!
>
> Sorry for not getting back to you earlier. I got busy with other
> issues and forgot about this review.
>
> On 2015-09-21 20:08, Jon Masamitsu wrote:
>> Bengt,
>>
>> It's correct that if the else is taken
>>
>> 178 } else {
>> 179 // We don't want to update the marking status if a GC pause
>> 180 // is already underway.
>> 181 SuspendibleThreadSetJoiner sts_join;
>> 182 g1h->collector_state()->set_mark_in_progress(false);
>> 183 }
>>
>> then free_regions_coming() will always return false?
>> If yes, then the change looks good.
>
> Yes, this is correct. The flag for free_regions_coming is only set to
> true by the cleanup pause. And that is what is executed in the
> positive branch of the if-statement that you are looking at. So, in
> the else-branch free_regions_coming() will always return false. Not
> very nice and kind of fragile. But that's why it works.
>
>>
>> Also if you choose to move the block
>> of code (lines 185-214)
>>
>> 185 // Check if cleanup set the free_regions_coming flag. If it
>> 186 // hasn't, we can just skip the next step.
>> 187 if (g1h->free_regions_coming()) {
>> ...
>>
>> 214 }
>>
>> after
>>
>> 177 VMThread::execute(&op);
>>
>> I'll gladly code review the move of that code (but it is not
>> necessary).
>
> I agree with that code refactoring, but I'd prefer not to do it as
> part of this change.
That's fine.
>
> I discussed my proposed change with Per and we came to the conclusion
> that it will be confusing to have the "start concurrent" phase logging
> at the end of the stopped cleanup phase.
>
> It is instead better to leave it where it was before and just accept
> that the logging can be interleaved with the young GC logging. This is
> also a much smaller change. Just changing the join_sts parameter for
> the call to cm_log() to false.
So this latest change solves the hang problem but the logging
will be worse (more interleaving will occur)?
Jon
>
> Here's an updated webrev:
> http://cr.openjdk.java.net/~brutisso/8133706/webrev.01/
>
> With the upcoming logging changes for adapting the GC logging to the
> unified logging framework this will be a bit cleaner. Then the
> concurrent logging will be logged on separate lines.
>
> Thanks,
> Bengt
>
>
>>
>> Jon
>>
>> On 09/19/2015 04:19 AM, Bengt Rutisson wrote:
>>>
>>> Hi everyone,
>>>
>>> Could I have a couple of reviews for this change?
>>>
>>> http://cr.openjdk.java.net/~brutisso/8133706/webrev.00/
>>> https://bugs.openjdk.java.net/browse/JDK-8133706
>>>
>>> The bug report contains some good analysis from Eric Caspole, David
>>> Holmes and Yumin Qi.
>>>
>>> Thanks for this valuable investigation! Basically the problem is
>>> that the heap regions that can be reclaimed by the cleanup phase are
>>> not made available until they have been cleaned up in a concurrent
>>> phase. If a GC happens while we are doing the concurrent cleaning up
>>> of the free regions, the GC will wait for the concurrent cleaning to
>>> finish, either by calling new_region_try_secondary_free_list() or
>>> wait_while_free_regions_coming(). But since the logging before we
>>> start the concurrent cleaning is now joining the STS, that cleaning
>>> is getting blocked by the GC safepoint. So, we have a deadlock.
>>>
>>> This was actually documented in the ConcurrentMarkThread::run()
>>> method, but I missed that when I added the cm_log() calls.
>>>
>>> // Notify anyone who's waiting that there are no more free
>>> // regions coming. We have to do this before we join the STS
>>> // (in fact, we should not attempt to join the STS in the
>>> // interval between finishing the cleanup pause and clearing
>>> // the free_regions_coming flag) otherwise we might deadlock:
>>> // a GC worker could be blocked waiting for the notification
>>> // whereas this thread will be blocked for the pause to finish
>>> // while it's trying to join the STS, which is conditional on
>>> // the GC workers finishing.
>>>
>>>
>>> The simplest fix that I could come up with was to move the logging
>>> from the ConcurrentMarkThread::run() method in to the very end of
>>> the stopped part of the cleanup phase. This ensures that we don’t
>>> mix the log output with any logging that a GC does but id does not
>>> require joining the STS since we are already at a safepoint.
>>>
>>> I left the timing (logged as part of the “GC concurrent-cleanup-end”
>>> entry) unchanged. This means that there could be a slight mismatch
>>> between the timestamps for “concurrent-cleanup-start” and
>>> “concurrent-cleanup-end” and the time logged by
>>> “concurrent-cleanup-end”. I hope the simplicity of the change
>>> outweighs the disadvantage of this mismatch.
>>>
>>> Thanks,
>>> Bengt
>>
>
More information about the hotspot-gc-dev
mailing list