Warning: Due to various recent migrations, viewing non-HEAD refs may be broken.
/linux/io_uring/queue.ha (raw)
// SPDX-License-Identifier: MPL-2.0
// (c) 2021 Alexey Yerin <yyp@disroot.org>
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Eyal Sawady <ecs@d2evs.net>
// (c) 2025 Runxi Yu <me@runxiyu.org>
use errors;
use rt;
// TODO: Atomics
// Returns the next available [[sqe]] for this [[io_uring]], or null if the
// queue is full.
export fn ring_get_sqe(ring: *io_uring) nullable *sqe = {
const sq = &ring.sq;
const head = *sq.khead, next = sq.sqe_tail + 1;
if (next - head <= *sq.kring_entries) {
let sqe = &sq.sqes[sq.sqe_tail & *sq.kring_mask];
sq.sqe_tail = next;
return sqe;
};
return null;
};
fn needs_enter(ring: *io_uring, flags: *enter_flags) bool = {
if (ring.flags & ring_setup_flags::IOPOLL != ring_setup_flags::IOPOLL) {
return true;
};
if (*ring.sq.kflags & sq_flags::NEED_WAKEUP == sq_flags::NEED_WAKEUP) {
*flags |= enter_flags::SQ_WAKEUP;
return true;
};
return false;
};
fn needs_flush(ring: *io_uring) bool =
*ring.sq.kflags & sq_flags::CQ_OVERFLOW == sq_flags::CQ_OVERFLOW;
// Submits queued I/O asynchronously. Returns the number of submissions accepted
// by the kernel.
export fn ring_submit(ring: *io_uring) (uint | error) =
do_submit(ring, flush_sq(ring), 0u);
// Submits queued I/O asynchronously and blocks until at least "wait" events are
// complete. If ring_setup_flags::IOPOLL was configured for this ring, the meaning of
// the "wait" parameter is different: a non-zero value will block until at least
// one event is completed.
//
// Returns the number of submissions accepted by the kernel.
export fn ring_submit_and_wait(ring: *io_uring, wait: uint) (uint | error) =
do_submit(ring, flush_sq(ring), wait);
fn flush_sq(ring: *io_uring) uint = {
let sq = &ring.sq;
let ktail = *sq.ktail;
const mask = *sq.kring_mask;
if (sq.sqe_head == sq.sqe_tail) {
return ktail - *sq.khead;
};
for (let n = sq.sqe_tail - sq.sqe_head; n > 0; n -= 1u) {
sq.array[ktail & mask] = sq.sqe_head & mask;
ktail += 1u;
sq.sqe_head += 1u;
};
*sq.ktail = ktail;
return ktail - *sq.khead;
};
fn do_submit(
ring: *io_uring,
submitted: uint,
wait: uint,
) (uint | error) = {
let flags = enter_flags::GETEVENTS;
if (needs_enter(ring, &flags) || wait != 0) {
match (rt::io_uring_enter(ring.fd,
submitted, wait, flags, null)) {
case let err: rt::errno =>
return errors::errno(err);
case let n: uint =>
return n;
};
} else {
return submitted;
};
};