[project @ 2001-07-06 14:11:38 by simonmar]
authorsimonmar <unknown>
Fri, 6 Jul 2001 14:11:38 +0000 (14:11 +0000)
committersimonmar <unknown>
Fri, 6 Jul 2001 14:11:38 +0000 (14:11 +0000)
commit1c5d2a15cd2f8efc9c8bbafcf531248b4a02793a
tree5c4804b113ab2c729a9e5c915dfef7b2f16b7c6e
parent574b218dcfab79ec277beca2f729cc8ea8c078dc
[project @ 2001-07-06 14:11:38 by simonmar]
Fix a couple of nasty bugs in the take/putMVar implementation.

Now we keep the invariant that a full MVar only has blocked putMVars
on its queue, and an empty MVar only has blocked takeMVars on its
queue.  It was the absence of this invariant that led to accidental
deadlock before.

The second bug is that there was a window between a blocked thread
being restarted and it actually retrying the takeMVar/putMVar
operation when it could receive an exception, which would also lead to
deadlock.

The solution to both these problems (as suggested by Simon P.J.) is to
atomically wake up and perform the next blocked putMVar when we do a
take, and vice versa.  As a side effect, takeMVar & putMVar should be
much faster when blocking & restarting, because we now shortcut the
retrying of the blocked operation and we use a more specialised stack
layout for the blocked thread.  Unfortunately, things got more
complicated too, but there are comments explaining what's going on.
ghc/rts/HeapStackCheck.h
ghc/rts/HeapStackCheck.hc
ghc/rts/PrimOps.hc