Skip to main content

61  uring standard library

The uring module provides low-level Linux io_uring kernel submission and completion rings for non-blocking asynchronous system calls.

#use uring

61.1 Platform requirements

The uring module depends directly on the Linux kernel io_uring interface (kernel 5.1+). It is available exclusively on Linux targets.

[!NOTE] Even on supported kernels, environment policies (such as restrictive Docker seccomp profiles, unprivileged container namespaces, or system-wide kernel.io_uring_disabled sysctl settings) can cause uring::new to fail with runtime permission or operation errors.

61.2 Core structures

#type CQE (
   user_data: Int,
   res:       Int,
   flags:     Int
)

#type Ring (
   fd:          Int,
   sq_ptr:      Addr,
   sq_sz:       Int,
   sqes_ptr:    Addr,
   sqes_sz:     Int,
   cq_ptr:      Addr,
   cq_sz:       Int,
   sq_head_off: Int,
   sq_tail_off: Int,
   sq_mask_off: Int,
   sq_arr_off:  Int,
   cq_head_off: Int,
   cq_tail_off: Int,
   cq_mask_off: Int,
   cq_cqes_off: Int,
   sq_entries:  Int,
   cq_entries:  Int
)

61.3 Function catalog

Function Signature Description
uring::new Int => < Ring | String > Initializes an io_uring ring with the requested number of submission queue entries
uring::prep_nop Ring, Int => <> Prepares a no-operation submission; returns <-> if the queue is full
uring::prep_read Ring, Int, Addr, Int, Int => <> Prepares an asynchronous read at current file offset (-1), advancing position on completion
uring::prep_read_at Ring, Int, Addr, Int, Int, Int => <> Prepares an asynchronous read at an explicit file offset (off), preserving file position
uring::prep_write Ring, Int, Addr, Int, Int => <> Prepares an asynchronous write at current file offset (-1), advancing position on completion
uring::prep_write_at Ring, Int, Addr, Int, Int, Int => <> Prepares an asynchronous write at an explicit file offset (off), preserving file position
uring::prep_pipe_read Ring, Int, Addr, Int, Int => <> Prepares an asynchronous stream/pipe/PTY read (off = 0)
uring::prep_pipe_write Ring, Int, Addr, Int, Int => <> Prepares an asynchronous stream/pipe/PTY write (off = 0)
uring::prep_close Ring, Int, Int => <> Prepares an asynchronous file descriptor close operation
uring::prep_send Ring, Int, Addr, Int, Int, Int => <> Prepares an asynchronous socket send operation
uring::prep_recv Ring, Int, Addr, Int, Int, Int => <> Prepares an asynchronous socket receive operation
uring::prep_accept Ring, Int, Addr, Addr, Int, Int => <> Prepares an asynchronous socket accept operation
uring::prep_timeout Ring, Addr, Int, Int, Int => <> Prepares a timer- or completion-count-based timeout
uring::prep_timeout_ms Ring, Addr, Int, Int => <> Populates a 16-byte Timespec at ts_ptr from timeout_ms and prepares OP_TIMEOUT
uring::prep_cancel Ring, Int, Int => <> Prepares an asynchronous cancellation request targeting a 64-bit user_data
uring::sq_space Ring => Int Returns the number of available slots remaining in the submission queue
uring::submit Ring => Int Enters kernel and submits pending SQEs via io_uring_enter
uring::submit_and_wait Ring, Int => Int Submits pending SQEs and blocks until at least wait_nr CQEs complete
uring::peek_cqe Ring => < CQE | > Non-blocking check for a completion event; copies CQE before advancing head pointer
uring::wait_cqe Ring => < CQE | String > Checks for ready CQE or blocks via submit_and_wait(ring, 1)
uring::reap Ring => CQEs Drains all currently ready CQEs into a growable array
uring::drain_pipes Ring, PipeFds => < PipeOutputs | String > Multiplexes concurrent async OP_READ submissions across multiple pipes until EOF
uring::close Ring => () Unmaps submission/completion ring memory and closes the ring file descriptor

61.4 Operational semantics

61.4.1 Submission queue capacity

Submission queue preparation (prep_*) checks available ring capacity (sq_space(ring)). If the ring is full, preparation returns <-> immediately without modifying sq_tail or overwriting pending submissions. Callers must invoke uring::submit to flush pending entries and free ring capacity.

61.4.2 Buffer lifetimes and memory stability

Standard operations (prep_read, prep_write, prep_send, prep_recv) use ordinary buffered/page-cache I/O rather than zero-copy memory registrations. The memory buffers passed as Addr are borrowed by the kernel for the duration of the asynchronous operation. User code must ensure buffers remain valid, unmoved, and unfreed until the corresponding completion event (CQE) has been reaped.

uring::close(ring) immediately unmaps the ring buffers and closes the kernel file descriptor. Rings must not be closed while operations referencing user buffers remain outstanding.

61.4.3 Completion queue results

Completed operations report kernel status in CQE.res: - Success: Non-negative value (res >= 0), such as the number of bytes transferred. - Error: Negative value (res < 0), matching the negative Linux errno (for example, -62 for -ETIME on timeout expiration, or -125 for -ECANCELED).

61.5 Example

#use io
#use uring

ring_res = uring::new(8)
ring_res
   | ring =>
      uring::prep_nop(ring, 100)
      uring::submit(ring)
      cqe_opt = uring::wait_cqe(ring)
      cqe_opt
         | cqe => io::out(cqe.user_data)
      uring::close(ring)