[concurrency-interest] Can a volatile read be reordered before a lazySet?

Hans Boehm boehm at acm.org
Wed Dec 31 21:41:14 EST 2014

In my view, if we have

> while (pong.get() == 0);

it is certainly possible that some number of the loads become visible
before the store.  But I don't believe the intent in either Java or C++,
was to allow the compiler to defer the  store until after the loop, causing
this to deadlock.

This is largely a question of which progress guarantees are provided:  This
transformation makes it look to the programmer as though visibility of the
lazySet is delayed indefinitely for no reason.  Both languages are very
careful in what they actually promise in this respect because some real
implementations do in fact provide very weak guarantees.  At least at the
time of the Java memory model, there were non-preemptive threads
implementations, in which threads could stall indefinitely for no good
reason except the existence of other runnable threads.  As earlier messages
point out, hardware architectures also typically don't provide an iron-clad
guarantee that store buffers drain in a finite amount of time under all
conditions, though in practice they tend do so quite quickly (otherwise
e.g. spin-lock releases would not become visible to other threads, which
would be bad).

So I think the somewhat unsatisfactory bottom line here is that there is no
clear-cut, always-applicable, prohibition against compiler movement of the
lazySet/release store (though 17.4.9 imposes some restrictions for Java),
but I would consider it very poor quality of implementation to actually do
do.  I don't think this would deadlock for any real implementations.


On Wed, Dec 31, 2014 at 10:32 AM, Vitaly Davidovich <vitalyd at gmail.com>

> I don't know the exact mechanics of draining, but I suspect it happens
> when the cacheline is fetched and/or RFO completes on it.  The way I
> understand it is core wants to write but either doesn't have the cacheline
> or needs to obtain ownership of it; while that request is outstanding, the
> write is put into the store buffer.  Once the line is available, the write
> is applied to it from the buffer.
> I'd welcome someone with more details to correct/enhance my understanding.
> Sent from my phone
> On Dec 31, 2014 11:50 AM, "Oleksandr Otenko" <oleksandr.otenko at oracle.com>
> wrote:
>>  yes, I got you, and my clumsy question really should have read "upon
>> what condition will they drain on their own"
>> Like, N tics? Coherence traffic ceased? Hyperthreaded sibling does
>> something?
>> Alex
>> On 31/12/2014 16:36, Vitaly Davidovich wrote:
>> Your previous reply talked about performing a lazy write and then
>> possibly having it stall indefinitely (or until preemption, as you say)
>> because nobody forces the buffer to drain.  I'm saying if the write
>> actually occurs, it'll drain on its own.
>> Sent from my phone
>> On Dec 31, 2014 11:31 AM, "Oleksandr Otenko" <oleksandr.otenko at oracle.com>
>> wrote:
>>>  Yes, but do they drain if no one writes anything?
>>> Alex
>>> On 31/12/2014 15:18, Vitaly Davidovich wrote:
>>> Write buffers don't *need* to be drained, they drain automatically
>>> anyway.  At least that's the case for intel.  So the issue here is more
>>> like what Gil said - compiler can reorder the code causing a deadlock.
>>> Sent from my phone
>>> On Dec 31, 2014 9:45 AM, "Oleksandr Otenko" <oleksandr.otenko at oracle.com>
>>> wrote:
>>>>  Not sure why you say (3). Since lazySet is not part of JMM, I am only
>>>> assuming it is pretty much like an ordered store on x86.
>>>> In the presence of write buffers the loop may spin indefinitely, yet
>>>> the lazy-stored write won't become visible to the pong thread - there'd be
>>>> nothing to cause the buffers of the ping thread to flush. So ping
>>>> effectively will appear to perform all the loads of the indefinite loop
>>>> ahead of the store.
>>>> In reality the only event that would cause the write buffers to flush,
>>>> is the thread preemption.
>>>> Alex
>>>> On 31/12/2014 07:20, Nitsan Wakart wrote:
>>>> Re-read the Shipilev "JMM Pragmatics" reference again last night, and
>>>> discussed with Gil. I think that cup of coffee was nowhere near enough :-).
>>>> In particular:
>>>>  "If IUC this means stores and volatile loads are conservatively not
>>>> reordered" is FALSE because the premise "IUC" is false. I did not
>>>> understand correctly which leads me to amend my comment:
>>>> 1. There's technically nothing to stop reordering between the store and
>>>> load.
>>>>  >  theLong.lazySet(1L);
>>>> >  Object o = theRef.get();
>>>>  2. There's technically nothing to stop reordering between the store
>>>> and load.
>>>> >  long l = theLong.get() + 1; // LOADLOAD
>>>> >  theLong.lazySet(l); //STORESTORE
>>>> >  Object o = theRef.get(); // LOADLOAD
>>>>  3. I still think the while loop presents a different case to normal
>>>> flow. So for now I still hold that the lazySet cannot be moved after the
>>>> while loop.
>>>>  My sincere apologies for the confusion.
>>>> Happy holidays to all.
>>>> _______________________________________________
>>>> Concurrency-interest mailing listConcurrency-interest at cs.oswego.eduhttp://cs.oswego.edu/mailman/listinfo/concurrency-interest
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20141231/3c57999f/attachment.html>

More information about the Concurrency-interest mailing list