<div dir="ltr"><div>Hi Ryan,<br><br></div>It's a little late here, but I've tried to put all my thoughts in order on this topic.<br><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, May 4, 2014 at 9:18 PM, Ryan Newton <span dir="ltr"><<a href="mailto:rrnewton@gmail.com" target="_blank">rrnewton@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>Hi John & Carter,</div><div>
<br></div><div>Deferring for a moment issues with CAS on lazy/pointer values, which pertain to Carter's question, I want to understand the ordering concern WRT only the "IntArray" primops that Johan listed.  First, to my knowledge GHC doesn't do any reordering of effectful memory operations (e.g. readMutVar/writeMutVar).  That is, I thought that threaded "State#" param was ironclad from the compiler's point of view.  (In fact, if GHC does any optimization of these imperative bits, could someone point me to it?)</div>
</div></div></div></blockquote><div><br></div><div>My understanding is that GHC does do reordering of memory operations, in the CmmSink pass (<a href="http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/src/CmmSink.html">http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/src/CmmSink.html</a>, <a href="http://blog.ezyang.com/2014/01/so-you-want-to-add-a-new-concurrency-primitive-to-ghc/">http://blog.ezyang.com/2014/01/so-you-want-to-add-a-new-concurrency-primitive-to-ghc/</a>).  In particular ghc may currently reorder loads, although it doesn't seem to reorder stores (at this time).  And ghc *currently* only performs these reorderings in limited cases.<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">

<div><br></div><div>For Johan's primops to work, each primop must represent a full memory fence that is respected both by the architecture, and by <i>both</i> compilers (GHC & LLVM).  Since I don't think GHC is a problem, let's talk about LLVM.  We need to verify that LLVM understands not to float regular loads and stores past one of its own atomic instructions.  If that is the case (even without anything being marked "volatile"), then I think we are in ok shape, right?</div>
</div></div></div></blockquote><div><br></div><div>Provided the operations are SequentiallyConsistent (could probably use Acquire/Release for reads/writes) I think LLVM will handle this appropriately.<br></div><div> </div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">

<div><br></div><div>In the grand scheme of things isn't this a place where purity has done us good?  All the memory traffic related to pure computation is and should be separate from these primops on mutable vars and arrays, and there shouldn't need to be any special ordering constraints <i>between</i> those two classes, should there?</div>
</div></div></div></blockquote><div><br></div><div>Perhaps.  But it's still important to get ordering right WRT multiple mutable ops, so I'm not sure that purity actually helps that much, except that we can get away with underspecified operations moreso than in C++.  (also x86 has a stronger model than other archs, it's possible that we currently get away with stuff that's unsafe on other platforms)<br>
<br></div><div>I have to confess that I don't understand what you mean by suggesting we should implement these primops without having an underlying memory model.  What does <span class="">atomicReadIntArray</span><span class=""># mean if there's no memory model in which its defined?  How can you be sure that other ghc hackers won't break some assumptions that the implementations rely upon, if they don't have a memory model to describe how operations should behave?  This is strongly related to the TODO: in Johan's proposal: just because that may be true now (I don't know if it is!) doesn't mean it will remain so in the future.<br>
<br></span></div><div><span class="">Of course, given the limited number of GHC hackers, everything may work out fine in the end.  It just seems to me that it would be more sensible to define the semantics first and build the primops around them, rather than primops first and semantics later.<br>
<br>Best,<br>John<br></span></div><div><span class=""><br></span></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra">
<div class="gmail_quote">

<div><br></div><div>(Part 2)<b> CAS on lazy/pointer values</b> -- this bit <i>was </i>an ill-specified mess to begin with, for sure ;-).  In part, the problem was that it was somewhat unusual and <a href="https://github.com/rrnewton/haskell-lockfree/issues/10" target="_blank">sussed out other cabal/GHC</a> issues (including a <a href="https://github.com/rrnewton/haskell-lockfree/issues/28" target="_blank">regression in 7.8</a> that I think is a GHC bug,  but haven't filed yet [where a spurious "!" on a function arg of "Any" type changes behavior]).  Even once the commitment was made to use the "ticketed" approach.  (Carter, it's described <a href="https://ghc.haskell.org/trac/ghc/ticket/8157" target="_blank">in this trac ticket</a>.)</div>


<div><br></div><div>Johan, FYI, I think we should actually backpedal on casMutVar# and casArray# and not expose a type like the one we have in 7.8:</div><div><br></div><div><pre style="font-family:Consolas,'Liberation Mono',Courier,monospace;font-size:12px;margin-top:0px;margin-bottom:0px;color:rgb(51,51,51);line-height:18px">
<div style="padding-left:10px;min-height:18px">   <span style="color:rgb(153,0,115)">MutableArray</span><span># s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, a #)</span></div>

</pre></div><div><br></div><div>I can't think of any good reason to use it, since we should never trust that "a" return value -- it's poison, and covering it up successfully requires <a href="https://github.com/rrnewton/haskell-lockfree/issues/5" target="_blank">careful attention to NOINLINEs</a>.  Rather, for 7.10, better to commit directly IMHO to the "Any" type to beat back the compiler:</div>


<div><br></div><div><div>  casMutVarTicketed# :: MutVar# RealWorld a -> Any a -> Any a -></div><div>               State# RealWorld -> (# State# RealWorld, Int#, Any a #)</div></div><div><br></div><div><div>Cheers,</div>


<div>  -Ryan</div></div><div><div class="h5"><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

<div dir="ltr"><p>IMHO I think the desire to include these features is leading to a slightly cavalier attitude towards reordering concerns.  Even assuming that the Cmm code generator doesn't reorder reads/writes around `CallishMachOp`, I don't see why this behavior should always be true, leading to possible future pain.  Also, it's possible that LLVM may decide to reorder memory accesses AIUI because the underlying LLVM variables won't be synchronized.<br>



</p><p dir="ltr">In a nutshell, even though everything may work now I suspect it'll become an ill-specified mess in a few years time.  I don't have a ton of experience implementing these sorts of features in compilers though, so probably only worth a half cent.</p>



<p dir="ltr">John L.<br></p>
<div class="gmail_quote"><div><div>On May 4, 2014 3:10 AM, "Johan Tibell" <<a href="mailto:johan.tibell@gmail.com" target="_blank">johan.tibell@gmail.com</a>> wrote:<br type="attribution"></div>

</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div>

<div dir="ltr"><div>Hi,</div><div><br></div><div>I found myself needing atomic operations on basic, mutable numeric values. I wrote a short design doc that I'd like feedback on:</div><div><br></div><a href="https://ghc.haskell.org/trac/ghc/wiki/AtomicPrimops" target="_blank">https://ghc.haskell.org/trac/ghc/wiki/AtomicPrimops</a><br>






<div><br></div><div>I will try to implement these for 7.10.</div><div><br></div><div>-- Johan</div><div><br></div></div>
<br></div></div>_______________________________________________<br>
ghc-devs mailing list<br>
<a href="mailto:ghc-devs@haskell.org" target="_blank">ghc-devs@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/ghc-devs" target="_blank">http://www.haskell.org/mailman/listinfo/ghc-devs</a><br>
<br></blockquote></div>
</div>
<br>_______________________________________________<br>
ghc-devs mailing list<br>
<a href="mailto:ghc-devs@haskell.org" target="_blank">ghc-devs@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/ghc-devs" target="_blank">http://www.haskell.org/mailman/listinfo/ghc-devs</a><br>
<br></blockquote></div></div></div></div></div></blockquote></div></div></div></div></div>