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.
#import "Extensions/Io_Uring";
Procedures#
Syscalls#
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).
Registers resources with the ring (IORING_REGISTER_*, see io_uring_register_op).
Ring#
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_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.
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.
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.
Entries handed out by get_sqe and not yet submitted.
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.
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).
submit, then sleeps until at least wait_for completions are ready.
Completions ready to be consumed.
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.
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.
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.
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.
Consumes count completions at once (each CQE32 counts as one).
The buffer id of a completion that used a provided buffer (IORING_CQE_F_BUFFER).
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).
The 80 bytes of command data of a 128-byte entry (IORING_SETUP_SQE128), at offset 48.
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#
- FIXED_FILE_BIT
- IO_DRAIN_BIT
- IO_LINK_BIT
- IO_HARDLINK_BIT
- ASYNC_BIT
- BUFFER_SELECT_BIT
- CQE_SKIP_SUCCESS_BIT
- 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
- DATA
- SEND_FD
- 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
- BOUND
- UNBOUND
- MMAP
- INC
- REGISTER_OP
- STATIC_ADD_ID
- STATIC_DEL_ID
- DYNAMIC
- STATIC
- INACTIVE
- REGISTER_OP
- SQE_OP
- SQE_FLAGS_ALLOWED
- SQE_FLAGS_REQUIRED
- LAST
- SIOCINQ
- SIOCOUTQ
- GETSOCKOPT
- SETSOCKOPT
- TX_TIMESTAMP
- GETSOCKNAME
- DMABUF
- IMPORT
- RX_PAGE_SIZE
- FLUSH_RQ
- EXPORT
- LAST
- tv_sec: s64
- tv_nsec: s64
- opcode: u8
- flags: u8
- ioprio: u16
- fd: s32
- len: u32
- user_data: u64
- personality: u16
- flags: u16
- app_tag: u16
- len: u32
- addr: u64
- seed: u64
- rsvd: u64
- user_data: u64
- res: s32
- flags: u32
- big_cqe: [0] u64
- head: u32
- tail: u32
- ring_mask: u32
- ring_entries: u32
- flags: u32
- dropped: u32
- array: u32
- resv1: u32
- user_addr: u64
- head: u32
- tail: u32
- ring_mask: u32
- ring_entries: u32
- overflow: u32
- cqes: u32
- flags: u32
- resv1: u32
- user_addr: u64
- sq_entries: u32
- cq_entries: u32
- flags: u32
- sq_thread_cpu: u32
- sq_thread_idle: u32
- features: u32
- wq_fd: u32
- resv: [3] u32
- sq_off: io_sqring_offsets
- cq_off: io_cqring_offsets
- offset: u32
- resv: u32
- fds: u64
- user_addr: u64
- size: u64
- flags: u32
- id: u32
- mmap_offset: u64
- __resv: [4] u64
- region_uptr: u64
- flags: u64
- __resv: [2] u64
- nr: u32
- flags: u32
- resv2: u64
- data: u64
- tags: u64
- offset: u32
- resv: u32
- data: u64
- offset: u32
- resv: u32
- data: u64
- tags: u64
- nr: u32
- resv2: u32
- op: u8
- resv: u8
- flags: u16
- resv2: u32
- last_op: u8
- ops_len: u8
- resv: u16
- resv2: [3] u32
- ops: [0] io_uring_probe_op
- opcode: u16
- resv: u8
- resv2: [3] u32
- flags: u16
- nr_res: u16
- resv: [3] u32
- restrictions: [0] io_uring_restriction
- clockid: u32
- __resv: [3] u32
- src_fd: u32
- flags: u32
- src_off: u32
- dst_off: u32
- nr: u32
- pad: [3] u32
- addr: u64
- len: u32
- bid: u16
- resv: u16
- ring_addr: u64
- ring_entries: u32
- bgid: u16
- flags: u16
- resv: [3] u64
- buf_group: u32
- head: u32
- resv: [8] u32
- busy_poll_to: u32
- prefer_busy_poll: u8
- opcode: u8
- pad: [2] u8
- op_param: u32
- resv: u32
- min_wait_usec: u32
- flags: u32
- sigmask: u64
- sigmask_sz: u32
- pad: [3] u32
- pad2: [2] u64
- sigmask: u64
- sigmask_sz: u32
- min_wait_usec: u32
- ts: u64
- addr: u64
- fd: s32
- flags: u32
- timeout: __kernel_timespec
- opcode: u8
- pad: [7] u8
- pad2: [3] u64
- off: u32
- len: u32
- resv: u64
- namelen: u32
- controllen: u32
- payloadlen: u32
- flags: u32
- tv_sec: u64
- tv_nsec: u64
- off: u64
- len: u32
- __pad: u32
- off: u64
- __pad: u64
- head: u32
- tail: u32
- rqes: u32
- __resv2: u32
- __resv: [2] u64
- addr: u64
- len: u64
- rq_area_token: u64
- flags: u32
- dmabuf_fd: u32
- __resv2: [2] u64
- if_idx: u32
- if_rxq: u32
- rq_entries: u32
- flags: u32
- area_ptr: u64
- region_ptr: u64
- offsets: io_uring_zcrx_offsets
- zcrx_id: u32
- rx_buf_len: u32
- __resv: [3] u64
- __resv: [6] u64
- zcrx_fd: u32
- __resv1: [11] u32
- zcrx_id: u32
- op: u32
- __resv: [2] u64
- 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
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.
- cqe: io_uring_cqe
- extra: [2] u64
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.
- sqe: io_uring_sqe
- extension: [64] u8
Which opcodes the running kernel supports.
- last_op: u8
- the highest opcode the kernel knows
- supported: [256] bool
- indexed by opcode
Constants#
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).
errno values this module returns or tests for. They match on every Linux CPU.