LINUX.ORG.RU

История изменений

Исправление quasimoto, (текущая версия) :

какая польза от этого в задаче «запретить вызов kmalloc из прерывания»?

Вот:

nomalloc-выражение может состоять только из nomalloc-выражений; а «просто выражение» может состоять из «просто выражений» и nomalloc-выражений.

malloc работает в io, например:

malloc :: Size -> IO (Ptr CChar)
useMalloc :: Size -> IO ()
useMalloc bytes = do
  ptr <- malloc bytes
  write / read prt
  other io

если сделать производную обвёртку от IO:

-- IRQ <: IO
-- up-cast fromIRQ :: IRQ -> IO is safe
-- down-cast IRQ :: IO -> IRQ is unsafe
newtype IRQ a = IRQ { fromIRQ :: IO a } deriving ( Functor, Monad )

и _не_ экспортировать из соответствующего модуля конструктор IRQ :: IO a -> IRQ a, оставив только минимальный нужный интерфейс, то можно будет писать:

handler :: __ -> (__ -> IRQ some) -> IRQ IRQRetType
handler _ fn = do
  -- valid irq computations ...
  some <- fn __
  case some of
    _ -> return IRQ_HANDLED
    -- etc ...

но ни

foo = malloc

ни любое другое IO нельзя:

handler _ fn = do
  foo 100500 -- Couldn't match type `IO' with `IRQ'

вместо конструктора IRQ можно оставить unsafeIO2IRQ для желающих. Аналогично можно разбросать вычисления на большее количество уровней - IO :> Log только для логов, IO :> MM для памяти, IO :> Log :> IRQ (но не MM :> IRQ). Работает за счёт разных вещей - zero-cost newtype, возможность писать императивный код исключительно как монадические комбинаторы обеспечивающие некую форму последовательного выполнения и биндингов в IO, do-нотация, соответственно, rank-1 параметрический полиморфизм и соответствующие проверки типов, сокрытие имён в модулях.

Исправление quasimoto, :

какая польза от этого в задаче «запретить вызов kmalloc из прерывания»?

Вот:

nomalloc-выражение может состоять только из nomalloc-выражений; а «просто выражение» может состоять из «просто выражений» и nomalloc-выражений.

malloc работает в io, например:

malloc :: Size -> IO (Ptr CChar)
useMalloc :: Size -> IO ()
useMalloc bytes = do
  ptr <- malloc bytes
  write / read prt
  other io

если сделать производную обвёртку от IO:

-- IRQ <: IO
-- up-cast fromIRQ :: IRQ -> IO is safe
-- down-cast IRQ :: IO -> IRQ is unsafe
newtype IRQ a = IRQ { fromIRQ :: IO a } deriving ( Functor, Monad )

и _не_ экспортировать из соответствующего модуля конструктор IRQ :: IO a -> IRQ a, оставив только минимальный нужный интерфейс, то можно будет писать:

handler :: __ -> (__ -> IRQ some) -> IRQ IRQRetType
handler _ fn = do
  -- valid irq computations ...
  some <- fn __
  case some of
    _ -> return IRQ_HANDLED
    -- etc ...

но ни

foo = malloc

ни любое другое IO нельзя:

handler _ fn = do
  foo 100500 -- Couldn't match type `IO' with `IRQ'

вместо конструктора IRQ можно оставить unsafeIO2IRQ для желающих. Аналогично можно разбросать вычисления на большее количество уровней - IO :> Log только для логов, IO :> MM для памяти, IO :> Log :> IRQ (но не MM :> IRQ). Работает за счёт разных вещей - zero-cost newtype, общепринятость do-нотации как сахара для комбинаторов обеспечивающих некую форму последовательного выполнения и биндингов в Monad, rank-1 полиморфизм и соответствующие проверки типов, сокрытие имён в модулях.

Исходная версия quasimoto, :

какая польза от этого в задаче «запретить вызов kmalloc из прерывания»?

Вот:

nomalloc-выражение может состоять только из nomalloc-выражений; а «просто выражение» может состоять из «просто выражений» и nomalloc-выражений.

malloc работает в io, например:

malloc :: Size -> IO (Ptr CChar)
useMalloc :: Size -> IO ()
useMalloc bytes = do
  ptr <- malloc bytes
  write / read prt
  other io

если сделать производную обвёртку от IO:

-- IRQ <: IO
-- up-cast fromIRQ :: IRQ -> IO is safe
-- down-cast IRQ :: IO -> IRQ is unsafe
newtype IRQ a = IRQ { fromIRQ :: IO a } deriving ( Functor, Monad )

и _не_ экспортировать из соответствующего модуля конструктор IRQ :: IO a -> IRQ a, оставив только минимальный нужный интерфейс, то можно будет писать:

handler :: __ -> (__ -> IRQ some) -> IRQ IRQRetType
handler _ fn = do
  -- valid irq computations ...
  some <- fn __
  case some of
    _ -> return IRQ_HANDLED
    -- etc ...

но ни

foo = malloc

ни любое другое IO нельзя:

handler _ fn = do
  foo 100500 -- Couldn't match type `IO' with `IRQ'

вместо конструктора IRQ можно оставить unsafeIO2IRQ для желающих. Аналогично можно разбросать вычисления на большее количество уровней - IO :> Log только для логов, IO :> MM для памяти, IO :> Log :> IRQ (но не MM :> IO). Работает за счёт разных вещей - zero-cost newtype, общепринятость do-нотации как сахара для комбинаторов обеспечивающих некую форму последовательного выполнения и биндингов в Monad, rank-1 полиморфизм и соответствующие проверки типов, сокрытие имён в модулях.