[concurrency-interest] DCL using Fence Intrinsics

Oleksandr Otenko oleksandr.otenko at oracle.com
Fri Mar 13 11:02:50 EDT 2015


First you need to justify the saving of loadFence. You can't assume the 
saving is significant (first it must be predictable) and at the same 
time assume the load of a / breaking the loop is not predictable.

Alex

On 13/03/2015 14:55, Vitaly Davidovich wrote:
> So I thought it might be shady, but I can't come up with a 
> *legitimate* case where it breaks.  One possibility is following 
> reordering:
>
> else {
>     do {
>  U.loadFence();
>         // sink the 'a' read into here, it's still 0, then 'b' reads 1 
> and we break
>     }while(b!=1);
>
> I can't immediately see why such a transformation would take place 
> because for compiler to do that, it would have to prove that the loop 
> always executes only once (otherwise it's moving a load ahead of a 
> loadFence).  It's also making a loop invariant read into a variant 
> one.  I guess it could clone the code into 2 separate versions, one 
> for looping and one for not, but seems weird and useless.  I suppose 
> CPU could speculate somehow here, but again, not immediately clear to 
> me why it would speculate ahead of 'b' when 'b' is read possibly many 
> times and 'a' is read just once.
>
> But you're right, this "trick" isn't reliable.
>
>
>
> On Fri, Mar 13, 2015 at 10:33 AM, Oleksandr Otenko 
> <oleksandr.otenko at oracle.com <mailto:oleksandr.otenko at oracle.com>> wrote:
>
>     No, you have just shown that you don't need a loadFence after the
>     loop, which is wrong.
>
>     You need a loadFence between the last load of b and the load of a,
>     to preserve the order of loading a after loading b. Then you need
>     a loadFence between loads of b, so you keep re-loading b on each
>     iteration.
>
>     Alex
>
>
>     On 13/03/2015 14:23, Vitaly Davidovich wrote:
>>     btw, for #3, you'd probably want to rewrite T2 as:
>>
>>     if (b==1) {
>>        U.loadFence();
>>     } else {
>>         do {
>>            U.loadFence();
>>         }while(b!=1);
>>     }
>>
>>     assert(a==1);
>>
>>     This would avoid an additional load fence upon exiting the while
>>     loop (if the while loop was actually entered).
>>
>>
>>     On Fri, Mar 13, 2015 at 10:10 AM, Vitaly Davidovich
>>     <vitalyd at gmail.com <mailto:vitalyd at gmail.com>> wrote:
>>
>>         Yeah, I read #2 as the while loop being in T1, but if it's
>>         T2, then yes, it's fine and will work.
>>
>>         Thanks for clarifying #3 -- I meant to keep existing code as
>>         is but stuff a loadFence into the loop, but re-reading my
>>         reply, I do see how it can be interpreted as moving the
>>         existing one.
>>
>>         On Fri, Mar 13, 2015 at 9:50 AM, Oleksandr Otenko
>>         <oleksandr.otenko at oracle.com
>>         <mailto:oleksandr.otenko at oracle.com>> wrote:
>>
>>             On 12/03/2015 23:01, Vitaly Davidovich wrote:
>>>
>>>             1 works, and I can't see why you even need the loadFence.
>>>
>>>             2 and 3 won't (always) work.  In 2, compiler can move
>>>             a=1 after the loop.  For 3, if you put loadFence inside
>>>             the while loop it will work.
>>>
>>
>>             If we assume the loop in 2 was meant to be in T2, then it
>>             will work.
>>
>>             For 3, you need to have loadFence inside the loop /and/
>>             after the loop.
>>
>>             Alex
>>
>>
>>>             sent from my phone
>>>
>>>             On Mar 12, 2015 6:43 PM, "vikas"
>>>             <vikas.vksingh at gmail.com
>>>             <mailto:vikas.vksingh at gmail.com>> wrote:
>>>
>>>                 Hi,
>>>
>>>                   I am trying to understand the fence intrinsic api.
>>>                   Pershing has showw how to write DCL in C++ in his blog
>>>                 http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/
>>>
>>>                   I was trying to have a similar thing in Java (*Code1*)
>>>
>>>                      sun.misc.Unsafe U;
>>>                      Singleton instance = null
>>>
>>>                      Singleton getInstance() {
>>>                           Singleton tmp = instance;
>>>                          * U.loadFence();*
>>>                           if(tmp == null) {
>>>                 synchronized(Singleton.class) {
>>>                                    tmp = instance;
>>>                  if(tmp == null) {
>>>                  tmp = new Singleton();
>>>                  *U.storeFence();*
>>>                  instance = tmp;
>>>                                   }
>>>                               }
>>>                            }
>>>                        return tmp;
>>>                      }
>>>                             *Code1*
>>>
>>>                    * Will the above Code1 works? *
>>>
>>>
>>>                 ------------------------------------------------------------------------------
>>>
>>>                     On similar lines i have another doubt. See below
>>>                 *Code2*.
>>>                     if * a* and *b* are normal variables with
>>>                 initial value 0
>>>
>>>                        T1              T2
>>>                      a = 1;
>>>                 while(unsafe.getIntVolatile(b)!=1);
>>>                  unsafe.putIntOrdered(b,1);        assert(a==1); //
>>>                 *will always pass*
>>>
>>>                              *Code2*
>>>
>>>                     Code2 works because putXXXOrdered and
>>>                 getXXXVolatile forms a happens
>>>                 before edge.
>>>                     i.e. assert in Thread T2 will always pass.
>>>
>>>
>>>                 -------------------------------------------------------------------------------
>>>                     But can we say the same thing for below code
>>>                 (*Code3*)
>>>
>>>                        T1                 T2
>>>                      a = 1;          while(b!=1);
>>>                  unsafe.storeFence();  unsafe.loadFence();
>>>                      b = 1;          assert(a==1);
>>>                              *Code3*
>>>
>>>                   * /What  prevents the compiler to optimize the
>>>                 while loop in *Code3* to an
>>>                 infinte loop./*
>>>                    So does *Code3 *works? If not, then is there
>>>                 anyway we can achieve the
>>>                    expected behavior using fences.
>>>
>>>                    thanks
>>>                    vikas
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>                 --
>>>                 View this message in context:
>>>                 http://jsr166-concurrency.10961.n7.nabble.com/DCL-using-Fence-Intrinsics-tp12420.html
>>>                 Sent from the JSR166 Concurrency mailing list
>>>                 archive at Nabble.com.
>>>                 _______________________________________________
>>>                 Concurrency-interest mailing list
>>>                 Concurrency-interest at cs.oswego.edu
>>>                 <mailto:Concurrency-interest at cs.oswego.edu>
>>>                 http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>
>>>
>>>
>>>             _______________________________________________
>>>             Concurrency-interest mailing list
>>>             Concurrency-interest at cs.oswego.edu  <mailto: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/20150313/b9390d77/attachment-0001.html>


More information about the Concurrency-interest mailing list