Modules

Io_Uring

moduleextensionSource

Available on Linux

#import "Extensions/Io_Uring";

Procedures#

Syscalls#

(entries: u32, params: *io_uring_params) -> s32

Creates a ring of at least entries submission entries. params goes in (flags, and the CPU and idle time of an SQPOLL thread) and comes back filled in: the real sizes, features and the offsets to map. Returns the ring's file descriptor.

(fd: s32, to_submit: u32, min_complete: u32, flags: u32, argument: *void, argument_bytes: u64) -> s32

Submits to_submit entries and/or waits for min_complete completions, depending on flags (IORING_ENTER_*). argument is a signal mask, or an io_uring_getevents_arg with IORING_ENTER_EXT_ARG, and argument_bytes its size (8 for a mask).

(fd: s32, opcode: u32, argument: *void, count: u32) -> s32

Registers resources with the ring (IORING_REGISTER_*, see io_uring_register_op).

Ring#

ring_initsince 0.31.0Source
(ring: *Ring, entries: u32, flags: u32 = 0) -> s32

Creates a ring of at least entries submission entries (a power of two, the kernel rounds up) and maps it. flags are IORING_SETUP_* flags. Returns 0, or the negative errno of the failing step: -ENOSYS where the kernel has no io_uring, -EPERM where policy forbids it (a seccomp filter, kernel.io_uring_disabled), -ENOMEM when the locked-memory limit of an old kernel is too small. IORING_SETUP_NO_MMAP, SQE_MIXED, CQE_MIXED and SQ_REWIND change the memory layout in ways this type does not follow: they return -EINVAL; drive such rings with the system calls directly.

(ring: *Ring, entries: u32, params: *io_uring_params) -> s32

ring_init with every parameter: params goes in (flags, cq_entries with IORING_SETUP_CQSIZE, the SQPOLL thread's CPU and idle time, wq_fd with ATTACH_WQ) and comes back as the kernel filled it in.

ring_deinitsince 0.31.0Source
(ring: *Ring)

Unmaps the ring and closes its descriptor. Safe on a ring that was never initialized or already closed. Pending operations are dropped by the kernel.

get_sqesince 0.31.0Source
(ring: *Ring) -> *io_uring_sqe

The next free submission entry, zeroed, or null when the submission queue is full (submit, then ask again). Fill it in (prep_rw, prep_nop or by hand), set user_data, and call submit. With IORING_SETUP_SQE128 the entry is 128 bytes: cast it to io_uring_sqe128.

sq_pendingsince 0.31.0Source
(ring: *Ring) -> u32

Entries handed out by get_sqe and not yet submitted.

publish_sqessince 0.31.0Source
(ring: *Ring) -> u32

Publishes the entries handed out so far, so the kernel can see them, and returns how many it has not yet taken. Does not enter the kernel; submit does.

submitsince 0.31.0Source
(ring: *Ring) -> s32

Publishes the pending entries and tells the kernel about them. Returns how many it took, or a negative errno (-EBUSY: completions are backed up, reap some first; -EAGAIN: out of resources).

(ring: *Ring, wait_for: u32) -> s32

submit, then sleeps until at least wait_for completions are ready.

peek_cqesince 0.31.0Source
(ring: *Ring, cqe: **io_uring_cqe) -> s32

The oldest unconsumed completion in cqe, without waiting: returns 0, or -EAGAIN when there is none. The pointer stays valid until cqe_seen. A ring that only produces completions when it enters the kernel (DEFER_TASKRUN, IOPOLL, or one with overflowed completions) is entered once to collect them.

wait_cqesince 0.31.0Source
(ring: *Ring, cqe: **io_uring_cqe) -> s32

Waits until a completion is ready and returns it in cqe (see peek_cqe). Submitted entries must have been passed to submit first. Returns 0 or a negative errno.

(ring: *Ring, cqe: **io_uring_cqe, nanoseconds: s64) -> s32

wait_cqe with a limit: returns -ETIME when no completion arrived within nanoseconds. Needs IORING_FEAT_EXT_ARG (Linux 5.11); returns -EOPNOTSUPP without it.

cqe_seensince 0.31.0Source
(ring: *Ring, cqe: *io_uring_cqe)

Marks cqe, the one peek_cqe or wait_cqe returned, as consumed, handing its slot back to the kernel. The pointer must not be used afterwards.

cq_advancesince 0.31.0Source
(ring: *Ring, count: u32)

Consumes count completions at once (each CQE32 counts as one).

prep_rwsince 0.31.0Source
(sqe: *io_uring_sqe, opcode: io_uring_op, fd: s32, address: *void, length: u32, offset: u64)

Sets the fields most operations share: read, write, accept, send, recv... address and length describe the buffer, offset the file position (or the operation's second argument).

sqe_commandsince 0.31.0Source
(sqe: *io_uring_sqe) -> *u8

The 80 bytes of command data of a 128-byte entry (IORING_SETUP_SQE128), at offset 48.

probe_opssince 0.31.0Source
(ring: *Ring, probe: *Probe) -> s32

Asks the kernel which operations it supports (IORING_REGISTER_PROBE, Linux 5.6). Returns 0, or -EINVAL on an older kernel, where only the original operations exist.

Types#

:: enum
FIXED_FILE_BIT
IO_DRAIN_BIT
IO_LINK_BIT
IO_HARDLINK_BIT
ASYNC_BIT
BUFFER_SELECT_BIT
CQE_SKIP_SUCCESS_BIT
:: enum
NOP
READV
WRITEV
FSYNC
READ_FIXED
WRITE_FIXED
POLL_ADD
POLL_REMOVE
SYNC_FILE_RANGE
SENDMSG
RECVMSG
TIMEOUT
TIMEOUT_REMOVE
ACCEPT
ASYNC_CANCEL
LINK_TIMEOUT
CONNECT
FALLOCATE
OPENAT
CLOSE
FILES_UPDATE
STATX
READ
WRITE
FADVISE
MADVISE
SEND
RECV
OPENAT2
EPOLL_CTL
SPLICE
PROVIDE_BUFFERS
REMOVE_BUFFERS
TEE
SHUTDOWN
RENAMEAT
UNLINKAT
MKDIRAT
SYMLINKAT
LINKAT
MSG_RING
FSETXATTR
SETXATTR
FGETXATTR
GETXATTR
SOCKET
URING_CMD
SEND_ZC
SENDMSG_ZC
READ_MULTISHOT
WAITID
FUTEX_WAIT
FUTEX_WAKE
FUTEX_WAITV
FIXED_FD_INSTALL
FTRUNCATE
BIND
LISTEN
RECV_ZC
EPOLL_WAIT
READV_FIXED
WRITEV_FIXED
PIPE
NOP128
URING_CMD128
LAST
:: enum
REGISTER_BUFFERS
UNREGISTER_BUFFERS
REGISTER_FILES
UNREGISTER_FILES
REGISTER_EVENTFD
UNREGISTER_EVENTFD
REGISTER_FILES_UPDATE
REGISTER_EVENTFD_ASYNC
REGISTER_PROBE
REGISTER_PERSONALITY
UNREGISTER_PERSONALITY
REGISTER_RESTRICTIONS
REGISTER_ENABLE_RINGS
REGISTER_FILES2
REGISTER_FILES_UPDATE2
REGISTER_BUFFERS2
REGISTER_BUFFERS_UPDATE
REGISTER_IOWQ_AFF
UNREGISTER_IOWQ_AFF
REGISTER_IOWQ_MAX_WORKERS
REGISTER_RING_FDS
UNREGISTER_RING_FDS
REGISTER_PBUF_RING
UNREGISTER_PBUF_RING
REGISTER_SYNC_CANCEL
REGISTER_FILE_ALLOC_RANGE
REGISTER_PBUF_STATUS
REGISTER_NAPI
UNREGISTER_NAPI
REGISTER_CLOCK
REGISTER_CLONE_BUFFERS
REGISTER_SEND_MSG_RING
REGISTER_ZCRX_IFQ
REGISTER_RESIZE_RINGS
REGISTER_MEM_REGION
REGISTER_QUERY
REGISTER_ZCRX_CTRL
REGISTER_BPF_FILTER
REGISTER_LAST
REGISTER_USE_REGISTERED_RING
:: struct
opcode: u8
flags: u8
ioprio: u16
fd: s32
len: u32
user_data: u64
personality: u16
:: struct
head: u32
tail: u32
ring_mask: u32
ring_entries: u32
flags: u32
dropped: u32
array: u32
resv1: u32
user_addr: u64
:: struct
head: u32
tail: u32
ring_mask: u32
ring_entries: u32
overflow: u32
cqes: u32
flags: u32
resv1: u32
user_addr: u64
:: struct
busy_poll_to: u32
prefer_busy_poll: u8
opcode: u8
pad: [2] u8
op_param: u32
resv: u32
RingstructforeignSource
:: struct
fd: s32
flags: u32
IORING_SETUP_* the ring was created with
features: u32
IORING_FEAT_* the kernel reports
sq_entries: u32
sq_mask: u32
sq_head: *u32
advanced by the kernel
sq_tail: *u32
advanced by submit
sq_flags: *u32
IORING_SQ_*
sq_dropped: *u32
sq_array: *u32
the index array, null with IORING_SETUP_NO_SQARRAY
sqes: *u8
sqe_bytes: u32
64, or 128 with IORING_SETUP_SQE128
sqe_head: u32
entries get_sqe handed out that submit has not published yet start here
sqe_tail: u32
and the next get_sqe hands out this one
cq_entries: u32
cq_mask: u32
cq_head: *u32
advanced by cqe_seen
cq_tail: *u32
advanced by the kernel
cq_flags: *u32
IORING_CQ_*
cq_overflow: *u32
cqes: *u8
cqe_bytes: u32
16, or 32 with IORING_SETUP_CQE32
sq_ring: *void
sq_ring_bytes: u64
cq_ring: *void
the same mapping as sq_ring with IORING_FEAT_SINGLE_MMAP
cq_ring_bytes: u64
sqes_bytes: u64
:: struct

A 32-byte completion, as a ring created with IORING_SETUP_CQE32 delivers. Cast the *io_uring_cqe that peek_cqe and wait_cqe give you to this; extra is the 16 bytes the operation filled in.

extra: [2] u64
:: struct

A 128-byte submission entry, as a ring created with IORING_SETUP_SQE128 hands out. The first 64 bytes are an ordinary io_uring_sqe; sqe_command gives the 80 bytes of command data from offset 48.

extension: [64] u8
ProbestructforeignSource
:: struct

Which opcodes the running kernel supports.

last_op: u8
the highest opcode the kernel knows
supported: [256] bool
indexed by opcode

Constants#

:: 425

The three io_uring system calls. Each returns what the kernel returns: 0 or more on success and a negative errno on failure, never -1 with an errno to read afterwards. The numbers are the same on every Linux CPU that has io_uring (x86-64 and arm64 share the generic range).

:: 1

errno values this module returns or tests for. They match on every Linux CPU.