Hi John & Carter,

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?)

For Johan's primops to work, each primop must represent a full memory fence that is respected both by the architecture, and by both 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?

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 between those two classes, should there?

(Part 2) CAS on lazy/pointer values -- this bit was an ill-specified mess to begin with, for sure ;-).  In part, the problem was that it was somewhat unusual and sussed out other cabal/GHC issues (including a regression in 7.8 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 in this trac ticket.)

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:


   MutableArray# s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, a #)

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 careful attention to NOINLINEs.  Rather, for 7.10, better to commit directly IMHO to the "Any" type to beat back the compiler:

  casMutVarTicketed# :: MutVar# RealWorld a -> Any a -> Any a ->
               State# RealWorld -> (# State# RealWorld, Int#, Any a #)

Cheers,
  -Ryan


 

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.

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.

John L.

On May 4, 2014 3:10 AM, "Johan Tibell" <johan.tibell@gmail.com> wrote:
Hi,

I found myself needing atomic operations on basic, mutable numeric values. I wrote a short design doc that I'd like feedback on:

https://ghc.haskell.org/trac/ghc/wiki/AtomicPrimops

I will try to implement these for 7.10.

-- Johan


_______________________________________________
ghc-devs mailing list
ghc-devs@haskell.org
http://www.haskell.org/mailman/listinfo/ghc-devs


_______________________________________________
ghc-devs mailing list
ghc-devs@haskell.org
http://www.haskell.org/mailman/listinfo/ghc-devs