RFR: 8079315: UseCondCardMark broken in conjunction with CMS precleaning

Aleksey Shipilev aleksey.shipilev at oracle.com
Tue Jun 2 09:25:32 UTC 2015

On 05/21/2015 03:54 PM, Erik Österlund wrote:
> Den 12/05/15 23:49 skrev Aleksey Shipilev <aleksey.shipilev at oracle.com>:
>> On 12.05.2015 23:44, Erik Österlund wrote:
>>> I don¹t know what windows does because it¹s open source but we only have
>>> x86 there and its hardware has no support for doing it any other way
>>> than with IPI messages which is all we need. And if we feel that scared,
>>> windows has a system call that does exactly what we want and with the
>>> architecture I propose it¹s trivial to specialize the barrier for
>>> windows do use this instead.
>> I think I get what you tell, but I am not convinced. The thing about
>> reading stuff in the mutator is to align the actions in collector with
>> the actions in mutator. So what if you push the IPI to all processors.
>> Some lucky processor will get that interrupt *after* (e.g. too late!)
>> both the reference store and (reordered/stale) card mark read => same
>> problem, right? In other words, asking a mutator to do a fence-like op
>> after an already missed card mark update solves what?
> The IPI will be received for sure on all processors after mprotect begins
> and before it ends. Otherwise they wouldn't serve any purpose. The purpose
> of the cross call is to shoot down TLBs and make the new permissions
> visible. If IPIs were to be delayed until after mprotect returns, it
> simply would not work. And this is all we need.

I still don't get it. AFAIU, it is not enough to delay precleaning until
every mutator flushes their stores. My point is that we need to
coordinate with mutator to at least make the reads and writes in the
proper order? Or we are hoping that whatever mechanics
global_store_fence is using restores the program order? And how that
helps against the compiler reorderings?

Suppose x.a = prev and card[@x.a] = dirty. Mutator is about to write x.a
= cur.

preclean: if (card[@x.a] == dirty)
preclean:    card[@x.a] = precleaned

mutator:  card_state = card[@x.a]; // reads "dirty"

preclean: global_store_fence();
mutator:  <well, okay; flush the write buffers>

preclean: read x.a
preclean: <okay, I've got: x.a = prev; card[@x.a] = precleaned>

mutator:  x.a = cur;
mutator:  StoreStore
mutator:  if (card_state != dirty)
mutator:     card[@x.a] = dirty;   // does not happen!

preclean: <okay, I've got: x.a = cur;  card[@x.a] = precleaned>

End result: the card mark update for "x.a = cur" is lost.


More information about the hotspot-dev mailing list