Hello,
I wonder if it might be possible to use just one primitive which atomically changes the interrupt mask for a thread? Here is an example of what I'm thinking:
data MaskingState = Unmasked
| MaskedInterruptible
| MaskedNonInterruptible
-- Atomically changes the interrupt mask for a thread, and returns the old mask.
setMask :: MaskingState -> IO MaskingState
setMask = error "primitive?"
-- Change the mask for the duration of an IO action.
-- The action is passed the old mask.
scopedSetMask :: MaskingState -> (MaskingState -> IO a) -> IO a
scopedSetMask m io = do m1 <- setMask m
a <- io m1
setMask m1
return a
-- Change the mask for the duration of an IO action.
scopedSetMask_ :: MaskingState -> IO a -> IO a
scopedSetMask_ m io = scopedSetMask m $ \_ ->
io
-- Simon's mask:
mask :: ((IO a -> IO a) -> IO b) -> IO b
mask f = scopedSetMask MaskedInterruptible $ \m ->
f (scopedSetMask_ m)