blockio-uring-0.1.0.0: src/System/IO/BlockIO/URingFFI.hsc
{-# LANGUAGE CApiFFI #-}
{-# LANGUAGE InterruptibleFFI #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# OPTIONS_GHC -fobject-code #-}
{-# OPTIONS_GHC -Wno-missing-export-lists #-}
module System.IO.BlockIO.URingFFI where
import Foreign
import Foreign.C
import Prelude hiding (head, tail)
import System.Posix.Types
#include <liburing.h>
data {-# CTYPE "liburing.h" "struct io_uring" #-} URing = URing
instance Storable URing where
sizeOf _ = #{size struct io_uring}
alignment _ = #{alignment struct io_uring}
peek _ = return URing
poke _ _ = return ()
foreign import capi unsafe "liburing.h io_uring_queue_init"
io_uring_queue_init :: CUInt -> Ptr URing -> CUInt -> IO CInt
foreign import capi unsafe "liburing.h io_uring_queue_exit"
io_uring_queue_exit :: Ptr URing -> IO ()
foreign import capi safe "liburing.h io_uring_queue_init_params"
io_uring_queue_init_params :: CUInt -> Ptr URing -> Ptr URingParams -> IO CInt
iORING_SETUP_CQSIZE :: CUInt
iORING_SETUP_CQSIZE = #{const IORING_SETUP_CQSIZE}
data {-# CTYPE "liburing.h" "struct io_uring_params" #-}
URingParams = URingParams {
sq_entries :: !CUInt,
cq_entries :: !CUInt,
flags :: !CUInt,
features :: !CUInt
-- Note: this is a subset of all the fields. These are
-- just the ones we need now or are likely too need.
-- If you need more, just add them.
}
deriving stock (Show, Eq)
instance Storable URingParams where
sizeOf _ = #{size struct io_uring_params}
alignment _ = #{alignment struct io_uring_params}
peek p = do sq_entries <- #{peek struct io_uring_params, sq_entries} p
cq_entries <- #{peek struct io_uring_params, cq_entries} p
flags <- #{peek struct io_uring_params, flags} p
features <- #{peek struct io_uring_params, features} p
return URingParams {..}
poke p ps = do -- As we only cover a subset of the fields, we must clear
-- the remaining fields we don't set to avoid them
-- containing arbitrary values.
fillBytes p 0 #{size struct io_uring_params}
#{poke struct io_uring_params, sq_entries} p (sq_entries ps)
#{poke struct io_uring_params, cq_entries} p (cq_entries ps)
#{poke struct io_uring_params, flags} p (flags ps)
#{poke struct io_uring_params, features} p (features ps)
--
-- Submitting I/O
--
data {-# CTYPE "liburing.h" "struct io_uring_sqe" #-} URingSQE
foreign import capi unsafe "liburing.h io_uring_get_sqe"
io_uring_get_sqe :: Ptr URing -> IO (Ptr URingSQE)
#ifdef LIBURING_HAVE_DATA64
foreign import capi unsafe "liburing.h io_uring_sqe_set_data64"
io_uring_sqe_set_data :: Ptr URingSQE -> CULong -> IO ()
#else
io_uring_sqe_set_data :: Ptr URingSQE -> CULong -> IO ()
io_uring_sqe_set_data p user_data =
do #{poke struct io_uring_sqe, user_data} p user_data
#endif
foreign import capi unsafe "liburing.h io_uring_prep_read"
io_uring_prep_read :: Ptr URingSQE -> Fd -> Ptr Word8 -> CUInt -> CULong -> IO ()
foreign import capi unsafe "liburing.h io_uring_prep_write"
io_uring_prep_write :: Ptr URingSQE -> Fd -> Ptr Word8 -> CUInt -> CULong -> IO ()
foreign import capi unsafe "liburing.h io_uring_prep_nop"
io_uring_prep_nop :: Ptr URingSQE -> IO ()
foreign import capi unsafe "liburing.h io_uring_submit"
io_uring_submit :: Ptr URing -> IO CInt
--
-- Collecting I/O
--
data {-# CTYPE "liburing.h" "struct io_uring_cqe" #-}
URingCQE = URingCQE {
cqe_data :: !CULong,
cqe_res :: !CInt
}
deriving stock Show
instance Storable URingCQE where
sizeOf _ = #{size struct io_uring_cqe}
alignment _ = #{alignment struct io_uring_cqe}
peek p = do cqe_data <- #{peek struct io_uring_cqe, user_data} p
cqe_res <- #{peek struct io_uring_cqe, res} p
return URingCQE { cqe_data, cqe_res }
poke _ _ = return ()
foreign import capi safe "liburing.h io_uring_wait_cqe"
io_uring_wait_cqe :: Ptr URing -> Ptr (Ptr URingCQE) -> IO CInt
foreign import capi unsafe "liburing.h io_uring_peek_cqe"
io_uring_peek_cqe :: Ptr URing -> Ptr (Ptr URingCQE) -> IO CInt
foreign import capi unsafe "liburing.h io_uring_cqe_seen"
io_uring_cqe_seen :: Ptr URing -> Ptr URingCQE -> IO ()