Memory fence around stg_atomicModifyMutVarzh

Hello, I've been trying to figure out where exactly the synchronisation guarantee of `atomicModifyIORef` comes from, I've gone down a bit of a rabbit-hole of function calls and macro expansions, and wanted to check I'd got the right idea. **Assumption:** `stg_atomicModifyMutVarzh` imposes a barrier to reordering, as described in the Data.IORef documentation. Call tree: stg_atomicModifyMutVarzh dirty_MUT_VAR recordClosureMutated recordMutableCap allocBlock_lock ACQUIRE_SM_LOCK -> ACQUIRE_LOCK -> pthread_mutex_lock **Conclusion:** `pthread_mutex_lock` imposes a memory barrier, and it is through this rather indirect chain of function calls that `stg_atomicModifyMutVarzh` gets its barrier property. Is this correct? Or is there a more direct barrier invocation that I have missed? Thanks. -- Michael Walker (http://www.barrucadu.co.uk)

Michael Walker
Hello,
I've been trying to figure out where exactly the synchronisation guarantee of `atomicModifyIORef` comes from, I've gone down a bit of a rabbit-hole of function calls and macro expansions, and wanted to check I'd got the right idea.
**Assumption:** `stg_atomicModifyMutVarzh` imposes a barrier to reordering, as described in the Data.IORef documentation.
Call tree:
stg_atomicModifyMutVarzh dirty_MUT_VAR recordClosureMutated recordMutableCap allocBlock_lock ACQUIRE_SM_LOCK -> ACQUIRE_LOCK -> pthread_mutex_lock
**Conclusion:** `pthread_mutex_lock` imposes a memory barrier, and it is through this rather indirect chain of function calls that `stg_atomicModifyMutVarzh` gets its barrier property.
Is this correct? Or is there a more direct barrier invocation that I have missed?
I'm afraid I don't know off the top of my head but hopefully Simon Marlow will be able to shed some more light here. When he does it would be great if you could write a nice comment explaining this logic and either open a Phabricator Diff or send the text to me so I can merge it. Cheers, - Ben

On 21/10/2015 13:17, Ben Gamari wrote:
Michael Walker
writes: Hello,
I've been trying to figure out where exactly the synchronisation guarantee of `atomicModifyIORef` comes from, I've gone down a bit of a rabbit-hole of function calls and macro expansions, and wanted to check I'd got the right idea.
**Assumption:** `stg_atomicModifyMutVarzh` imposes a barrier to reordering, as described in the Data.IORef documentation.
Call tree:
stg_atomicModifyMutVarzh dirty_MUT_VAR recordClosureMutated recordMutableCap allocBlock_lock ACQUIRE_SM_LOCK -> ACQUIRE_LOCK -> pthread_mutex_lock
**Conclusion:** `pthread_mutex_lock` imposes a memory barrier, and it is through this rather indirect chain of function calls that `stg_atomicModifyMutVarzh` gets its barrier property.
Is this correct? Or is there a more direct barrier invocation that I have missed?
I'm afraid I don't know off the top of my head but hopefully Simon Marlow will be able to shed some more light here.
When he does it would be great if you could write a nice comment explaining this logic and either open a Phabricator Diff or send the text to me so I can merge it.
Here is the barrier: (h) = ccall cas(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var, x, y); cas() is an external C function defined in includes/stg/SMP.h using inline assembly. Cheers Simon

I'm afraid I don't know off the top of my head but hopefully Simon Marlow will be able to shed some more light here.
When he does it would be great if you could write a nice comment explaining this logic and either open a Phabricator Diff or send the text to me so I can merge it.
Here is the barrier:
(h) = ccall cas(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var, x, y);
cas() is an external C function defined in includes/stg/SMP.h using inline assembly.
Wow, I really did miss it. Thanks for pointing it out. I also have a question about the sort of relaxed behaviours permitted. The Data.IORef docs say:
The implementation is required to ensure that reordering of memory operations cannot cause type-correct code to go wrong. In particular, when inspecting the value read from an IORef, the memory writes that created that value must have occurred from the point of view of the current thread.
but I'm not sure that's enough. This also seems clearly wrong, but is permitted by that restriction: λ> newIORef False >>= \ref -> writeIORef ref True >> readIORef ref False Is there a write-up anywhere of the memory model the GHC primitives give rise to? Or is it just one of those cases where the code is the specification? Thanks -- Michael Walker (http://www.barrucadu.co.uk)

Hi Michael,
I don't think you can take that paragraph as an exhaustive description of
what orderings are allowed. Edward Yang has a post about the current state
of GHC and memory models that I think is still how things are:
http://blog.ezyang.com/2014/01/so-you-want-to-add-a-new-concurrency-primitiv...
Ryan
On Wed, Oct 21, 2015 at 1:58 PM, Michael Walker
I'm afraid I don't know off the top of my head but hopefully Simon Marlow will be able to shed some more light here.
When he does it would be great if you could write a nice comment explaining this logic and either open a Phabricator Diff or send the text to me so I can merge it.
Here is the barrier:
(h) = ccall cas(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var, x, y);
cas() is an external C function defined in includes/stg/SMP.h using inline assembly.
Wow, I really did miss it. Thanks for pointing it out.
I also have a question about the sort of relaxed behaviours permitted. The Data.IORef docs say:
The implementation is required to ensure that reordering of memory operations cannot cause type-correct code to go wrong. In particular, when inspecting the value read from an IORef, the memory writes that created that value must have occurred from the point of view of the current thread.
but I'm not sure that's enough. This also seems clearly wrong, but is permitted by that restriction:
λ> newIORef False >>= \ref -> writeIORef ref True >> readIORef ref False
Is there a write-up anywhere of the memory model the GHC primitives give rise to? Or is it just one of those cases where the code is the specification?
Thanks
-- Michael Walker (http://www.barrucadu.co.uk) _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
participants (4)
-
Ben Gamari
-
Michael Walker
-
Ryan Yates
-
Simon Marlow