Liburing 2026.10.29
static
YoSTEALTH/Liburing

Prep: other

Poll, timeout, cancel, futex, msg_ring, nop, uring_cmd, epoll, ...

io_uring_prep_provide_buffers(sqe: SQE, addr: Buffer, nr: int, bgid: int, bid: int) -> bool#

Provides nr buffers of len(addr) // nr bytes each, laid out one after the other in addr.

Example

>>> area = bytearray(64)
>>> io_uring_prep_provide_buffers(sqe, area, 4, 1, 0)  # 4 buffers of 16 bytes: group 1, ids 0..3
True
Setup used to run this example
    'io_uring_sqe_set_data64', 'io_uring_sqe_set_flags', 'io_uring_sqe_set_buf_group',
    'io_uring_prep_nop', 'io_uring_prep_provide_buffers', 'Futex', 'timespec',
)  # fmt: skip
def sqe(ns):
    ns['sqe'] = io_uring_get_sqe(make_ring(ns))

Note

  • Linux 5.7+. cqe.res is 0 on success.
  • The buffer ids are bid to bid + nr - 1, all at most 65535 (OSError: E2BIG or OSError: EINVAL otherwise). A request uses the group with IOSQE_BUFFER_SELECT and io_uring_sqe_set_buf_group (reads and socket receives only, OSError: EINVAL otherwise; a vectored one with a single iov); its completion has IORING_CQE_F_BUFFER and the id in cqe.flags >> IORING_CQE_BUFFER_SHIFT.
  • A consumed buffer is forgotten by the kernel: provide it again to reuse it.
  • The kernel uses the buffers until they are consumed or removed, so the ring holds addr (locked: no resize) until its exit; giving a part of an area it already holds again takes nothing more.
  • sqe must come from io_uring_get_sqe or be an Sqe(ring) (TypeError for an Sqe template: no ring to hold addr).
  • ValueError if nr is less than 1 or addr is shorter than nr bytes.
  • Legacy: prefer a buffer ring (io_uring_setup_buf_ring), which needs no request per buffer.

io_uring_prep_remove_buffers(sqe: SQE, nr: int, bgid: int) -> bool#

Removes up to nr buffers of the group bgid that io_uring_prep_provide_buffers gave; cqe.res is the number removed.

Note

io_uring_prep_poll_add(sqe: SQE, fd: int, poll_mask: int) -> bool#

Polls fd once for the poll_mask events (POLLIN, POLLOUT, ...); the ready events are returned in cqe.res.

Note

  • Level triggered: an event pending at the submit completes it at once. One completion, then the poll is gone; poll again for the next event.
  • cqe.res raises OSError: ECANCELED after io_uring_prep_poll_remove or a cancel.

io_uring_prep_poll_multishot(sqe: SQE, fd: int, poll_mask: int) -> bool#

io_uring_prep_poll_add that stays armed: it posts a completion on every event, until removed.

Note

  • Linux 5.13+.
  • Each completion has IORING_CQE_F_MORE in cqe.flags. One without it is the last (an error, a remove or a cancel: cqe.res raises OSError: ECANCELED): submit a new poll to keep watching fd.
  • The first completion is level triggered, the following ones edge triggered: consume the event (read all the data) before the next one, or expect spurious completions.

io_uring_prep_poll_remove(sqe: SQE, user_data: int) -> bool#

Removes the poll request with user_data (the value you gave it).

Note

  • io_uring_prep_cancel64 that matches poll requests only. cqe.res: 0 when removed (the poll's own cqe.res raises OSError: ECANCELED); OSError: ENOENT when not found (it completed already), OSError: EALREADY when it is completing, too late to remove.

io_uring_prep_poll_update(sqe: SQE, old_user_data: int, new_user_data: int, poll_mask: int, flags: int | None = None) -> bool#

Updates the poll request old_user_data: its user_data to new_user_data and / or its events to poll_mask, whichever flags (default 0: nothing) select.

Flags

Note

  • Linux 5.13+.
  • Only the low 16 bits of the events (POLLIN, POLLOUT, ...) can change; EPOLLONESHOT, EPOLLEXCLUSIVE and EPOLLET can not: remove the poll and arm a new one.
  • cqe.res: 0 when done; OSError: ENOENT when not found (it completed already), OSError: EALREADY when it is completing, too late, OSError: ECANCELED when re-arming with poll_mask failed: the poll ends, its own completion says why.

io_uring_prep_nop(sqe: SQE) -> bool#

Does nothing and completes, cqe.res 0.

Example

>>> io_uring_prep_nop(sqe)
True
Setup used to run this example
    'io_uring_sqe_set_data64', 'io_uring_sqe_set_flags', 'io_uring_sqe_set_buf_group',
    'io_uring_prep_nop', 'io_uring_prep_provide_buffers', 'Futex', 'timespec',
)  # fmt: skip
def sqe(ns):
    ns['sqe'] = io_uring_get_sqe(make_ring(ns))

io_uring_prep_nop128(sqe: SQE) -> bool#

io_uring_prep_nop in a 128-byte entry (the ring needs IORING_SETUP_SQE128 or IORING_SETUP_SQE_MIXED).

Example

>>> io_uring_prep_nop128(sqe)
True
Setup used to run this example
def sqe128(ns):
    ns['sqe'] = io_uring_get_sqe128(make_ring(ns, flags=IORING_SETUP_SQE_MIXED))

io_uring_prep_timeout(sqe: SQE, ts: Timespec, count: int, flags: int | None = None) -> bool#

Completes after the time ts (Timespec, held until the completion) or after count other completions, whichever comes first; flags (default 0) are IORING_TIMEOUT_*.

Flags

Note

io_uring_prep_timeout_remove(sqe: SQE, user_data: int, flags: int | None = None) -> bool#

Removes the timeout request with user_data (the value you gave it); flags (default 0): the kernel accepts none yet.

Note

  • Linux 5.5+.
  • cqe.res: 0 when removed (the timeout's own cqe.res raises OSError: ECANCELED); OSError: ENOENT when not found (it fired already), OSError: EALREADY when it is firing, too late to remove.

io_uring_prep_timeout_update(sqe: SQE, ts: Timespec, user_data: int, flags: int | None = None) -> bool#

Updates the time of the timeout request with user_data (the value you gave it) to ts (held until the completion); flags (default 0): IORING_TIMEOUT_ABS for a point in time, the only one accepted.

Note

  • Linux 5.11+.
  • cqe.res: 0 when updated; OSError: ENOENT when not found (it fired already), OSError: EALREADY when it is firing, too late to update.

io_uring_prep_cancel64(sqe: SQE, user_data: int, flags: int | None = None) -> bool#

Cancels the in-flight request with user_data (the value you gave it); flags (default 0) are IORING_ASYNC_CANCEL_*.

Example

>>> sqe = io_uring_get_sqe(ring)
>>> io_uring_prep_cancel64(sqe, 123)
True
Setup used to run this example
    'io_uring_get_probe_ring', 'io_uring_ring_dontfork', 'io_uring_queue_exit', 'io_uring_register',
    'io_uring_set_iowait', 'io_uring_sq_ready', 'io_uring_sq_space_left', 'io_uring_sqring_wait', 'io_uring_get_sqe',
    'io_uring_get_events', 'io_uring_close_ring_fd', 'io_uring_register_ring_fd', 'io_uring_unregister_ring_fd',
    'io_uring_register_personality', 'io_uring_unregister_personality', 'io_uring_unregister_files',
    'io_uring_register_eventfd', 'io_uring_unregister_eventfd', 'io_uring_register_buffers', 'io_uring_buf_ring_head',
    'io_uring_register_iowq_aff', 'io_uring_register_iowq_max_workers', 'io_uring_cq_has_overflow',
    'io_uring_cq_eventfd_enabled', 'io_uring_cq_eventfd_toggle', 'BufReg', 'Napi', 'ClockRegister', 'Bpf', 'SQE',
    'SiginfoT', 'io_uring_prep_waitid', 'io_uring_prep_cancel', 'io_uring_prep_cancel64', 'ZcrxIfqReg',
)  # fmt: skip
def ring(ns):
    make_ring(ns)

Flags

Note

  • Linux 5.5+.
  • user_data names the first in-flight request with that value, also with IORING_ASYNC_CANCEL_ALL (each request has its own entry in the ring's table). To cancel a group, use io_uring_prep_cancel_fd(sqe, fd, IORING_ASYNC_CANCEL_ALL), or one cancel per request.
  • cqe.res: 0 when cancelled (with IORING_ASYNC_CANCEL_ALL / _ANY: how many); OSError: ENOENT when none was found (it completed already), OSError: EALREADY when it is running and past cancelling: wait for its own completion. The cancelled request's cqe.res raises OSError: ECANCELED (OSError: EINTR if it was running); either completion may come first.
  • Interruptible requests (sockets, poll, timeouts) cancel; disk I/O that has started does not.
  • IORING_ASYNC_CANCEL_OP (Linux 6.6+) needs the opcode in the entry's len, which SQE does not expose.

io_uring_prep_cancel(sqe: SQE, user_data: object, flags: int | None = None) -> bool#

Cancels the in-flight request whose object is user_data (io_uring_sqe_set_data: its user_data is the object's address); flags (default 0) are IORING_ASYNC_CANCEL_*. io_uring_prep_cancel64 takes an int user_data and lists the flags and results.

Type

user_data object

Example

>>> conn = {'fd': 5}
>>> sqe = io_uring_get_sqe(ring)
>>> io_uring_prep_cancel(sqe, conn)
True
Setup used to run this example
    'io_uring_get_probe_ring', 'io_uring_ring_dontfork', 'io_uring_queue_exit', 'io_uring_register',
    'io_uring_set_iowait', 'io_uring_sq_ready', 'io_uring_sq_space_left', 'io_uring_sqring_wait', 'io_uring_get_sqe',
    'io_uring_get_events', 'io_uring_close_ring_fd', 'io_uring_register_ring_fd', 'io_uring_unregister_ring_fd',
    'io_uring_register_personality', 'io_uring_unregister_personality', 'io_uring_unregister_files',
    'io_uring_register_eventfd', 'io_uring_unregister_eventfd', 'io_uring_register_buffers', 'io_uring_buf_ring_head',
    'io_uring_register_iowq_aff', 'io_uring_register_iowq_max_workers', 'io_uring_cq_has_overflow',
    'io_uring_cq_eventfd_enabled', 'io_uring_cq_eventfd_toggle', 'BufReg', 'Napi', 'ClockRegister', 'Bpf', 'SQE',
    'SiginfoT', 'io_uring_prep_waitid', 'io_uring_prep_cancel', 'io_uring_prep_cancel64', 'ZcrxIfqReg',
)  # fmt: skip
def ring(ns):
    make_ring(ns)

Note

  • Linux 5.5+.
  • user_data names the first in-flight request with that value, also with IORING_ASYNC_CANCEL_ALL (each request has its own entry in the ring's table). To cancel a group, use io_uring_prep_cancel_fd(sqe, fd, IORING_ASYNC_CANCEL_ALL), or one cancel per request.
  • cqe.res: 0 when cancelled (with IORING_ASYNC_CANCEL_ALL / _ANY: how many); OSError: ENOENT when none was found, OSError: EALREADY when past cancelling: wait for its own completion. The cancelled request's cqe.res raises OSError: ECANCELED (OSError: EINTR if it was running); either completion may come first.

io_uring_prep_cancel_fd(sqe: SQE, fd: int, flags: int | None = None) -> bool#

Cancels the in-flight requests of fd; flags (default 0) are IORING_ASYNC_CANCEL_* (IORING_ASYNC_CANCEL_ALL for all of them, not only the first; IORING_ASYNC_CANCEL_FD_FIXED, Linux 6.0+, when fd is a direct descriptor). IORING_ASYNC_CANCEL_FD is set already.

Note

  • Linux 5.19+.
  • cqe.res: 0 when cancelled (with IORING_ASYNC_CANCEL_ALL: how many); OSError: ENOENT when none was found, OSError: EALREADY when past cancelling: wait for its own completion. Each cancelled request's cqe.res raises OSError: ECANCELED (OSError: EINTR if it was running); the completions come in no fixed order.

io_uring_prep_link_timeout(sqe: SQE, ts: Timespec, flags: int) -> bool#

Limits the time of the previous request, linked to it with IOSQE_IO_LINK, to ts (Timespec, held until the completion); flags are IORING_TIMEOUT_ABS, IORING_TIMEOUT_BOOTTIME, IORING_TIMEOUT_REALTIME, IORING_TIMEOUT_ETIME_SUCCESS (as in io_uring_prep_timeout), or 0.

Note

  • Linux 5.5+.
  • Must directly follow the request it limits, and applies to that one only: to limit a whole chain, link it after the chain's last request. A chain of only a link timeout is invalid.
  • cqe.res raises OSError: ETIME when it expired: the linked request's cqe.res raises OSError: ECANCELED (OSError: EINTR if it was running), and so does the rest of its chain; OSError: ECANCELED when the linked request completed first; OSError: ENOENT when it was gone as the timer expired.

io_uring_prep_epoll_wait(sqe: SQE, fd: int, events: EpollEvent, maxevents: int, flags: int | None = None) -> bool#

Waits for events of the epoll fd, into events (held until the completion); maxevents is 1 to the size of EpollEvent(no=...), else ValueError. events must be one made with no=, not a single item.

Note

  • Linux 6.15+.
  • cqe.res is the number of events filled in, like epoll_wait(2); its errors raise OSError.
  • For event loops that still have epoll users: they can wait through the ring instead of adding the ring's fd to the epoll set.

io_uring_prep_epoll_ctl(sqe: SQE, epfd: int, fd: int, op: int, ev: EpollEvent) -> bool#

epoll_ctl(2) on the epoll epfd: op (EPOLL_CTL_ADD, EPOLL_CTL_MOD, EPOLL_CTL_DEL) for fd with the event ev (held until the completion; ignored by EPOLL_CTL_DEL).

Note

  • Linux 5.6+.
  • cqe.res is 0; the errors of epoll_ctl(2) raise OSError.

io_uring_prep_msg_ring_cqe_flags(sqe: SQE, fd: int, len: int, data: int, flags: int, cqe_flags: int) -> bool#

io_uring_prep_msg_ring that also sets the cqe.flags of the posted completion to cqe_flags (IORING_MSG_RING_FLAGS_PASS is set; flags adds to it).

Note

  • data is the target's cqe.user_data, below 2**63 (ValueError): Liburing sends it with bit 63 set, which tells the target ring the completion is a message, not one of its own requests.
  • The kernel may set further bits in the target's cqe.flags.

io_uring_prep_msg_ring(sqe: SQE, fd: int, len: int, data: int, flags: int | None = None) -> bool#

Posts a completion on another ring (fd, its ring_fd): user_data data, res len; flags (default 0) are IORING_MSG_RING_*.

Example

>>> sqe = io_uring_get_sqe(ring)
>>> io_uring_prep_msg_ring(sqe, other.ring_fd, 7, 1234)
True
>>> io_uring_submit(ring)
1
>>> io_uring_wait_cqe(other, cqe)
0
>>> cqe[0].user_data, cqe[0].res
(1234, 7)
Setup used to run this example
def message_rings(ns):
    make_ring(ns, entries=8)
    make_ring(ns, 'other', 8)
    ns['cqe'] = Cqe()

Note

  • data is the target's cqe.user_data, below 2**63 (ValueError): Liburing sends it with bit 63 set, which tells the target ring the completion is a message, not one of its own requests.
  • Linux 5.18+. Any ring you have access to is a target, this one included: a wake-up for whoever waits on it, or a 32 + 64 bit message (len, data).
  • This ring's cqe.res: 0 when posted; OSError: EBADFD when fd is not a ring or a disabled one, OSError: EOVERFLOW when the target's completion queue is full and overflowing.

io_uring_prep_msg_ring_fd(sqe: SQE, fd: int, source_fd: int, target_fd: int, data: int, flags: int | None = None) -> bool#

Sends the registered file source_fd of this ring to the slot target_fd of the ring fd; the target ring gets a completion with user_data data; flags (default 0) are IORING_MSG_RING_*.

Note

  • data is the target's cqe.user_data, below 2**63 (ValueError): Liburing sends it with bit 63 set, which tells the target ring the completion is a message, not one of its own requests.
  • Linux 6.0+. The target must be another ring (OSError: EINVAL for this one).
  • This ring's cqe.res: 0 when sent; OSError: EBADFD when fd is not a ring or a disabled one, OSError: ENFILE when the target's table is full, OSError: EOVERFLOW when the target's completion queue is full and overflowing.

io_uring_prep_msg_ring_fd_alloc(sqe: SQE, fd: int, source_fd: int, data: int, flags: int | None = None) -> bool#

io_uring_prep_msg_ring_fd, but the target ring picks a free slot, returned in its cqe.res.

Note

  • data is the target's cqe.user_data, below 2**63 (ValueError): Liburing sends it with bit 63 set, which tells the target ring the completion is a message, not one of its own requests.
  • Linux 6.0+. This ring's cqe.res: 0 when sent; OSError: ENFILE when the target's table has no free slot (the other errors as in io_uring_prep_msg_ring_fd).

io_uring_prep_uring_cmd(sqe: SQE, cmd_op: int, fd: int) -> bool#

Sends the file-specific command cmd_op to fd (IORING_OP_URING_CMD, an async ioctl(2)).

Note

  • Linux 5.19+.
  • Only cmd_op and fd are set (the reserved fields zeroed); a command's own operands live in the entry's command bytes, which SQE does not expose. cqe.res is whatever the driver returns.

io_uring_prep_uring_cmd128(sqe: SQE, cmd_op: int, fd: int) -> bool#

io_uring_prep_uring_cmd in a 128-byte entry (the ring needs IORING_SETUP_SQE128 or IORING_SETUP_SQE_MIXED).

Note

  • Only cmd_op and fd are set (the reserved fields zeroed); the 80 command bytes, which SQE does not expose, carry the command's own operands. cqe.res is whatever the driver returns.

io_uring_prep_waitid(sqe: SQE, idtype: int, id: int, infop: SiginfoT, options: int, flags: int | None = None) -> bool#

Waits for a child process's state change, like os.waitid: the kernel fills infop at the completion; idtype (os.P_PID, os.P_PGID, os.P_ALL, ...) and id pick the children, options (os.WEXITED, ...) the changes; flags (default 0) has no values yet.

Example

>>> pid = os.posix_spawn('/bin/sh', ['sh', '-c', 'exit 7'], os.environ)
>>> info = SiginfoT()
>>> sqe = io_uring_get_sqe(ring)
>>> io_uring_prep_waitid(sqe, os.P_PID, pid, info, os.WEXITED)
True
>>> io_uring_submit_and_wait(ring, 1)
1
>>> info.si_pid == pid, info.si_status
(True, 7)
Setup used to run this example
    'io_uring_get_probe_ring', 'io_uring_ring_dontfork', 'io_uring_queue_exit', 'io_uring_register',
    'io_uring_set_iowait', 'io_uring_sq_ready', 'io_uring_sq_space_left', 'io_uring_sqring_wait', 'io_uring_get_sqe',
    'io_uring_get_events', 'io_uring_close_ring_fd', 'io_uring_register_ring_fd', 'io_uring_unregister_ring_fd',
    'io_uring_register_personality', 'io_uring_unregister_personality', 'io_uring_unregister_files',
    'io_uring_register_eventfd', 'io_uring_unregister_eventfd', 'io_uring_register_buffers', 'io_uring_buf_ring_head',
    'io_uring_register_iowq_aff', 'io_uring_register_iowq_max_workers', 'io_uring_cq_has_overflow',
    'io_uring_cq_eventfd_enabled', 'io_uring_cq_eventfd_toggle', 'BufReg', 'Napi', 'ClockRegister', 'Bpf', 'SQE',
    'SiginfoT', 'io_uring_prep_waitid', 'io_uring_prep_cancel', 'io_uring_prep_cancel64', 'ZcrxIfqReg',
)  # fmt: skip
def ring(ns):
    make_ring(ns)

Note

  • Linux 6.7+.
  • The request holds infop until its completion.
  • cqe.res is 0 (infop says which child and how: si_pid, si_code, si_status); the errors of waitid(2) raise OSError (OSError: ECHILD: no such child).

io_uring_prep_futex_wake(sqe: SQE, futex: Futex, val: int, mask: int, futex_flags: int | None = None, flags: int | None = None) -> bool#

Wakes up to val waiters of futex whose wait mask matches mask; the number woken is returned in cqe.res. futex_flags are FUTEX2_* (default 0); futex is held until the completion.

Note

io_uring_prep_futex_wait(sqe: SQE, futex: Futex, val: int, mask: int, futex_flags: int | None = None, flags: int | None = None) -> bool#

Waits on futex while its value is val (matched with mask); futex_flags are FUTEX2_* (default 0); futex is held until the completion.

Note

io_uring_prep_futex_waitv(sqe: SQE, futex: Futex, flags: int | None = None) -> bool#

Waits on several futexes at once: Futex made with a vector (else ValueError), held until the completion; flags (default 0) has no values yet.

Note

  • Linux 6.7+.
  • Each entry of the vector carries its own value and mask (futex_waitv(2)); at most FUTEX_WAITV_MAX (128) entries.
  • cqe.res is the index of the entry that was woken; OSError: ECANCELED when cancelled. No timeout parameter: link an io_uring_prep_link_timeout after it.
Generated by tools/setu_docs.py from the docstrings of Liburing 2026.10.29 (CPython 3.14+).