[Haskell-cafe] Stupid newbie question of the day: why is newMVar in the IO monad

Ryan Yates fryguybob at gmail.com
Thu May 1 13:33:09 UTC 2014


There is extra work done to make this safe.  See the following:

https://github.com/ghc/ghc/blob/af6746fb6b5adb5ba5be6e0f647c4ebe767ce084/rts/sm/Storage.c#L305
https://ghc.haskell.org/trac/ghc/ticket/5558

Ryan


On Thu, May 1, 2014 at 8:25 AM, Mikulas Patocka <
mikulas at artax.karlin.mff.cuni.cz> wrote:

> > Also note linked from the global variables page on the wiki is:
> > http://www.haskell.org/haskellwiki/Top_level_mutable_state
> >
> > Important for the `unsafePerformIO` option is the NOINLINE pragma to
> ensure
> > that only one global variable exists.  In the STM case it is also
> important
> > to use `newTVarIO` rather then `unsafePerformIO $ atomically newTVar`
> which
> > does not work.
> >
> > Ryan
>
> Hi
>
> I think it isn't correct even with NOINLINE.
>
>
> Read the paper "Haskell on a Shared-Memory Multiprocessor"
> http://research.microsoft.com/pubs/67424/2005-haskell.pdf
>
> Among other things, the paper presents these ideas:
>
> (section 3.1) When multiple threads start to evaluate the same thunk
> concurrently, we could use interlocked compare-and-swap instruction to
> make sure that only one thread starts to evaluate it. However, the
> compare-and-swap instruction is slow and executing it at every thunk
> evaluation decreases performance. So, the designers avoid the
> compare-and-swap instruction (section 3.2) and consequently there is a
> race condition - there is a small window where two or more threads may
> evaluate the same thunk concurrently.
>
> Normally, this race condition doesn't matter, because Haskell is purely
> functional language, so when multiple threads evaluate the same thunk they
> end up with the same result - but in this particular example, where one is
> using unsafePerformIO to construct a unique variable, it can hurt, because
> you end up executing "unsafePerformIO $ newMVar 0" concurrently (section
> 3.5 of the paper).
>
>
> So - code like this isn't correct, the numbers returned by "uniq" may not
> be unique if we hit the race condition when evaluating "global":
>
> global :: MVar Integer
> global = unsafePerformIO $ newMVar 0
> {-# NOINLINE global #-}
> uniq = modifyMVar global (\i -> return (i+1,i))
>
>
> Has anything changed since that time, so that this construct is safe?
>
> Mikulas
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20140501/67d936b9/attachment.html>


More information about the Haskell-Cafe mailing list