Hi Phil, Thanks for the reply, however that just gives me a forced deadlock removal as before.
new bound thread (1) cap 0: schedule() cap 0: running thread 1 (ThreadRunGHC) cap 0: thread 1 stopped (blocked on an MVar) thread 1 @ 0000000003205388 is blocked on an MVar @ 00000000032040c8 (TSO_DIRTY) deadlocked, forcing major GC... all threads: threads on capability 0: other threads: thread 1 @ 0000000003205388 is blocked on an MVar @ 00000000032040c8 (TSO_DIRTY) cap 0: starting GC I don't believe any solution involving MVars will work for the non-threaded RTS. Though I'd love to be wrong here... Regards, Tamar On Sun, Jan 6, 2019 at 9:38 PM Phil Ruffwind <r...@rufflewind.com> wrote: > What if you wrap the MVar in a foreign closure? > > import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar) > import Control.Exception (bracket) > import Foreign.Ptr (FunPtr, freeHaskellFunPtr) > > foreign import ccall "wrapper" wrapAwaken :: IO () -> IO (FunPtr (IO > ())) > > main = do > mvar <- newEmptyMVar > bracket (wrapAwaken (putMVar mvar ())) freeHaskellFunPtr $ \ awaken > -> do > -- giveToExternalCode awaken > takeMVar mvar > > On Sun, Jan 6, 2019, at 10:37, Phyx wrote: > > Hi All, > > > > I'm looking for a way to block a task indefinitely until it is woken up > by > > an external event in both the threaded and non-threaded RTS and returns a > > value that was stored/passed. MVar works great for the threaded RTS, but > > for the non-threaded there's a bunch of deadlock detection in the > scheduler > > that would forcibly free the lock and resume the task with an opaque > > exception. This means that MVar and anything derived from it is not > usable. > > > > STMs are more expensive but also have the same deadlock code. So again no > > go. The reason it looks like a deadlock to the RTS is that the "Wake-up" > > call in the non-threaded rts will come from C code running inside the > RTS. > > The RTS essentially just sees all tasks blocked on it's main capability > and > > (usually rightly so) assumes a deadlock occurred. > > > > You have other states like BlockedOnForeign etc but those are not usable > as > > a primitive. Previous iterations of I/O managers have each invented > > primitives for this such as asyncRead#, but they are not general and > can't > > be re-used, and requires a different solution for threaded and > non-threaded. > > > > I have started making a new primitive IOPort for this, based on the MVar > > code, but this is not trivial... (currently I'm getting a segfault > > *somewhere* in the primitive's cmm code). The reason is that the > semantics > > are decidedly different from what MVars guarantee. I should also mention > > that this is meant to be internal to base (i.e no exported). > > > > So before I continue down this path and some painful debugging..., does > > anyone know of a way to block a task, unblock it later and pass a value > > back? It does not need to support anything complicated such as multiple > > take/put requests etc. > > > > Cheers, > > Tamar > > _______________________________________________ > > ghc-devs mailing list > > ghc-devs@haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs