
Peter Verswyvelen wrote:
I fail to understand this part of the code: case fromException e of Just ThreadKilled -> do myThreadId >>= killThread unblock (race a b)
So the current thread gets killed synchronously, then then the race function is evaluated again? The latter I don't get.
Let's look at what happens when an asynchronous exception arrives. The current thread gets killed. It gets killed asynchronously; as far as the RTS knows, the exceptionit might happen inside a pure computation which may be accessible to other threads. This means that the RTS has to patch things up so that reentering the corresponding thunks continues the computation - because another thread might need the value later. It does that by traversing the stack and turning update frames into ap nodes on the heap, and linking the entered thunks to those using an indirection (again, see RaiseAsync.c for details). Now in fact, IO actions are indistinguishable from pure computations by the RTS, so this mechanism also makes IO actions resumable, in principle, if you can access the corresponding thunk somehow. Normally you can't - there is no reference to that thunk - but unsafePerformIO gives you that reference. So in the above example, the current thread gets killed. However, the IO action (suspended right before the 'unblock (race a b)') is still accessible through the unsafePerformIO thunk. When another thread enters that thunk, execution resumes at that point. It may also be the same thread if it caught the exception further down the stack and later enters the unsafePerformIO thunk again. I don't understand all the interactions here - I don't know why the code is racy in the parallel RTS. Bertram