RFR: 8166811: Missing memory fences between memory allocation and refinement

Thomas Schatzl thomas.schatzl at oracle.com
Thu Nov 17 11:28:06 UTC 2016

Hi Kim,

  while unconsciously dwelling on the issue I think there is one
unanswered question:

On Thu, 2016-11-10 at 13:20 -0500, Kim Barrett wrote:
> > 
> > On Nov 8, 2016, at 7:52 AM, Thomas Schatzl <thomas.schatzl at oracle.c
> > om> wrote:
> > On Tue, 2016-10-25 at 19:13 -0400, Kim Barrett wrote:
> > > 
> > > There is still a situation where processing can fail, namely an
> > > in-progress humongous allocation that hasn't set the klass
> > > yet.  We
> > > continue to handle that as before.
> > - I am not completely sure about whether this case is handled
> > correctly. I am mostly concerned that the information used before
> > the
> > fence may not be the correct ones, but the checks expect them to be
> > valid.
> > 
> > Probably I am overlooking something critical somewhere.
> > 
> > A: allocates humongous object C, sets region type, issues
> > storestore, sets top pointers, writes the object, and then sets C.y
> > = x to mark a
> > card
> > 
> > Refinement: gets card (and assuming we have no further
> > synchronization
> > around which is not true, e.g. the enqueuing)
> > 
> >  592   if (!r->is_old_or_humongous()) {
> > 
> > assume refinement thread has not received the "type" correctly yet,
> > so must be Free. So the card will be filtered out incorrectly?
> > 
> > That is contradictory to what I said in the other email about the
> > comment discussion, but I only thoroughly looked at the comment
> > aspect there. :)
> > 
> > I think at this point in general we can't do anything but
> > !is_young(), as we can't ignore cards in "Free" regions - they may
> > be for cards for humongous ones where the thread did not receive
> > top and/or the type yet?

Here, combined with the scenario described in the other thread (I will
repeat it for clarity):

A: allocate new young region X, allocate object, storestore, stops at
the beginning of the dirty_young_block() method

B: allocate new object B in X, set B.y = something-outside, making the
card "Dirty" since thread A did not actually start doing
dirty_young_block() yet.

Refinement: scans the card; since R does not seem to synchronize with A
either, you may get a "dirty" card in a young (or free, depending on
whether the setting of the region flag in X has already been observed -
but it must be either one) region here in this case?

A: does the work in dirty_young_block()"

Since thread A allocated the region X, the top and region type of
region X are set by A.

Now, in this scenario, refinement gets the dirty card from thread B
first (because eg. it happens that thread B's queue just got full), and
A is still busy marking the card table.
The region type change (caused by A) for region X may not have been
observed by the refinement yet, so it may still be Free?

So the check in g1RemSet.cpp

 597   if (!r->is_old_or_humongous()) {

may filter the card out wrongly when processing the card from thread B
as far as I can see.

That's why I remarked about only being able to filter out using
is_young() here. For the refinement thread, "top" is current (after the
fence), but the region type not (may still be "Free" until the
refinement "synchronizes" with thread A in some way), doesn't it?

The change to "top" must have been observed already after the fence (in
line 684) though and is safe to use (the allocation of the TLAB for
thread B sets top using appropriate barriers, and the refinement will
synchronize with whatever thread B set).

Probably I am overlooking something about how the type of region X set by thread A can be visible to refinement if it only "synchronizes" with thread B (that did not write the type of region X).


More information about the hotspot-dev mailing list