37. 具体例: kernel スナッチ #2
lwpSuspend :: Lwp -> Lwp -> IO (Either ErrNo ())
lwpSuspend curl t = go $ lstat t
where go LsRun = fRunOnproc
go LsOnProc = fRunOnproc
go LsSleep = do lwpSetFlag lwWsuspend
if lwSintr . lflag $ t
then setRunnable t
else lwpUnlock t
return $ Right ()
go LsSuspended = do lwpUnlock t
return $ Right ()
go LsStop = do lwpSetFlag lwWsuspend
setRunnable t
return $ Right ()
go LsIdl = fIdlZomb
go LsZomb = fIdlZomb
fRunOnproc = do lwpSetFlag lwWsuspend
lwpNeedUserret t
lwpUnlock t
return $ Right ()
fIdlZomb = do lwpUnlock t
return $ Left Eintr
41. 具体例: デバドラ スナッチ #1
data UsbdBus = UsbdBus -- xxx
data SoftContext = SC { scBus :: UsbdBus
, iot :: Int
, ioh :: Int
, scOffs :: Int
, scEintrs :: Int
, scAsyncHead :: Ptr Int
, scIntrXfer :: Ptr Int }
type BusSpace m a = StateT SoftContext m a
type Addr = Int
ehciUsbsts, ehciUsbIntr :: Addr
ehciUsbsts = 0x04
ehciUsbIntr = 0x08
ehciStsIaa, ehciStsPcd, ehciStsErrInt, ehciStsInt :: Int
ehciStsIaa = 0x00000020
ehciStsPcd = 0x00000004
ehciStsErrInt = 0x00000002
ehciStsInt = 0x00000001
42. 具体例: デバドラ スナッチ #2
evalTmpl
:: Int -> (SoftContext -> IO a) -> Int -> BusSpace IO Int
evalTmpl
flag io ei | ei .&. flag /= 0 = go
| otherwise = return ei
where go = do sc <- get
liftIO . io $ sc
return $ ei .&. complement flag
evalWakeup, evalSoftIntr, evalPcd :: Int -> BusSpace IO Int
evalWakeup = evalTmpl ehciStsIaa $ wakeUp . scAsyncHead
evalSoftIntr = evalTmpl (ehciStsErrInt .|. ehciStsInt)
(usbSchedSoftIntr . scBus)
evalPcd = evalTmpl ehciStsPcd (sc -> ehciPcd sc . scIntrXfer $ sc)
evalWrite :: Int -> BusSpace IO ()
evalWrite ei = when (ei /= 0) go
where go = do sc <- get
let newEi = scEintrs sc .&. complement ei
put $ sc {scEintrs = newEi}
busSpaceOwrite4 ehciUsbIntr newEi