RFR: 8306334: Handle preemption of old cycle between filling and bootstrap phases [v2]
Y. Srinivas Ramakrishna
ysr at openjdk.org
Fri Apr 21 21:04:19 UTC 2023
On Thu, 20 Apr 2023 22:55:00 GMT, William Kemper <wkemper at openjdk.org> wrote:
>> src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp line 541:
>>
>>> 539: // have been preempted before we start a bootstrap cycle.
>>> 540: if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) {
>>> 541: if (heap->cancelled_gc()) {
>>
>> In most of the other states where cancellation is checked, we only check `heap->cancelled_gc()`, but here we first `check_cancellation_or_degen()` before checking `cancelled_gc()`.
>>
>> Now that method is below, where I have annotated some comments in between lines of code (github doesn't allow me to comment on lines not touched in a PR).
>>
>>
>> bool ShenandoahControlThread::check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point) {
>> ShenandoahHeap* heap = ShenandoahHeap::heap();
>> if (!heap->cancelled_gc()) {
>> return false;
>> }
>>
>>
>> In other words, if `check_cancellation_..` answers true, it must be be that `cancelled_gc()` is true already so the test at line 541 ~~is~~ seemed redundant at first blush. (Which was corrected upon reading further below.)
>>
>> However, there are more circumstances in which `check_cancellation_..` will answer true below.
>>
>>
>>
>> if (in_graceful_shutdown()) {
>> return true;
>> }
>>
>> assert(_degen_point == ShenandoahGC::_degenerated_outside_cycle,
>> "Should not be set yet: %s", ShenandoahGC::degen_point_to_string(_degen_point));
>>
>> if (is_alloc_failure_gc()) {
>> _degen_point = point;
>> return true;
>> }
>>
>> The assignment of `_degen_point = point` seems to be equivalent to assigning `_degen_point = ShenandoahGC::_degenerated_outside_cycle`, because of the assertion further above. So the comment in the assertion and the assignment further below look a bit fishy to me; as if code changed and these code paths may nt have been updated? Anyway, it seemed a bit confusing; such an assignment also happens further down in this method (code below).
>>
>>
>>
>> if (_preemption_requested.is_set()) {
>> assert(_requested_generation == YOUNG, "Only young GCs may preempt old.");
>> _preemption_requested.unset();
>>
>> // Old generation marking is only cancellable during concurrent marking.
>> // Once final mark is complete, the code does not check again for cancellation.
>> // If old generation was cancelled for an allocation failure, we wouldn't
>> // make it to this case. The calling code is responsible for forcing a
>> // cancellation due to allocation failure into a degenerated cycle.
>> _degen_point = point;
>> heap->clear_cancelled_gc(false /* clear oom handler */);
>> return true;
>> }
>>
>> I see that above we clear the cancellation, so I can see the case where `check_cancellation_` would answer true, but a subsequent `cancelled_gc` would not. So I see the case where we are doing the extra subsequent check after returning from this method. Still, this seems a bit subtle and I wonder if these could not be somehow made less subtle (and possibly cause confusion or maintenance issues). Anyway, this would be for some future clean-up.
>>
>>
>> fatal("Cancel GC either for alloc failure GC, or gracefully exiting, or to pause old generation marking");
>> return false;
>> }
>>
>>
>> Anyway, I thought I'd point this out, although I don't understand all of the various interactions here well enough to do a real review.
>
> Yes, the name `check_cancellation_or_degen` does not suggest at the complexity or side effects of the method.
>
>> The assignment of _degen_point = point seems to be equivalent to assigning _degen_point = ShenandoahGC::_degenerated_outside_cycle, because of the assertion further above.
>
> The assertion is checking the value of `_degen_point` _before_ the assignment, asserting that we do not overwrite a `_degen_point` that has already been set.
Of course, I don't know what I was thinking. Thanks!
-------------
PR Review Comment: https://git.openjdk.org/shenandoah/pull/262#discussion_r1174160415
More information about the shenandoah-dev
mailing list