commit b6b934c717f9474d0a67104172eb42c270dd77a0
parent 7ae6b0dfbe7000bd87aa0835a8658328b4f2677d
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 13 May 2021 20:20:43 -1000
linux::uring: initial commit
Diffstat:
3 files changed, 322 insertions(+), 0 deletions(-)
diff --git a/linux/uring/uring.ha b/linux/uring/uring.ha
@@ -0,0 +1,289 @@
+export def CQE_BUFFER_SHIFT: uint = 16;
+export def OFF_SQ_RING: u64 = 0;
+export def OFF_CQ_RING: u64 = 0x8000000;
+export def OFF_SQES: u64 = 0x10000000;
+
+// An io_uring [[sqe]] operation.
+export type op = enum u8 {
+ 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,
+};
+
+// A submission queue entry.
+export type sqe = struct {
+ opcode: op,
+ flags: sqe_flags,
+ ioprio: u16,
+ fd: i32,
+ union {
+ off: u64,
+ addr2: u64,
+ },
+ union {
+ addr: u64,
+ splice_off_in: u64,
+ },
+ length: u32,
+ union {
+ rw_flags: int,
+ fsync_flags: fsync_flags,
+ poll_events: u16,
+ poll32_events: u32,
+ sync_range_flags: u32,
+ msg_flags: u32,
+ timeout_flags: timeout_flags,
+ accept_flags: u32,
+ cancel_flags: u32,
+ open_flags: u32,
+ statx_flags: u32,
+ fadvise_advice: u32,
+ splice_flags: splice_flags,
+ },
+ user_data: u64,
+ union {
+ struct {
+ union {
+ buf_index: u16,
+ buf_group: u16,
+ },
+ personality: u16,
+ splice_fd_in: i32,
+ },
+ pad2: [3]u64,
+ },
+};
+
+// Flags for an [[sqe]].
+export type sqe_flags = enum u8 {
+ // Use fixed fileset
+ FIXED_FILE = 1 << 0,
+ // Issue after inflight IO
+ IO_DRAIN = 1 << 1,
+ // Links next sqe
+ IO_LINK = 1 << 2,
+ // Like LINK, but stronger
+ IO_HARDLINK = 1 << 3,
+ // Always go async
+ ASYNC = 1 << 4,
+ // Select buffer from sqe.buf_group
+ BUFFER_SELECT = 1 << 5,
+};
+
+// Flags for an fsync operation.
+export type fsync_flags = enum u32 {
+ DATASYNC = 1 << 0,
+};
+
+// Flags for a timeout operation.
+export type timeout_flags = enum u32 {
+ ABS = 1 << 0,
+};
+
+// Flags for a splice operation.
+export type splice_flags = enum u32 {
+ F_FD_IN_FIXED = 1 << 31,
+};
+
+// A completion queue entry.
+export type cqe = struct {
+ user_data: u64,
+ res: i32,
+ flags: cqe_flags,
+};
+
+// Flags for a [[cqe]].
+export type cqe_flags = enum u32 {
+ F_BUFFER = 1 << 0,
+};
+
+// Filled with the offset for mmap(2)
+export type sqring_offsets = struct {
+ head: u32,
+ tail: u32,
+ ring_mask: u32,
+ ring_entries: u32,
+ flags: sqring_flags,
+ dropped: u32,
+ array: u32,
+ resv1: u32,
+ resv2: u64,
+};
+
+// Flags for the sq ring.
+export type sqring_flags = enum u32 {
+ // Needs io_uring_enter wakeup
+ NEED_WAKEUP = 1 << 0,
+ // CQ ring is overflown
+ CQ_OVERFLOW = 1 << 1,
+};
+
+// Filled with the offset for mmap(2)
+export type cqring_offsets = struct {
+ head: u32,
+ tail: u32,
+ ring_mask: u32,
+ ring_entries: u32,
+ overflow: u32,
+ cqes: u32,
+ flags: cqring_flags,
+ resv1: u32,
+ resv2: u64,
+};
+
+// Flags for the cq ring.
+export type cqring_flags = enum u32 {
+ EVENTFD_DISABLED = 1 << 0,
+};
+
+// Flags for [[setup]].
+export type setup_flags = enum u32 {
+ // io_context is polled
+ IOPOLL = 1 << 0,
+ // SQ poll thread
+ SQPOLL = 1 << 1,
+ // sq_thread_cpu is valid
+ SQ_AFF = 1 << 2,
+ // App defines CQ size
+ CQSIZE = 1 << 3,
+ // Clamp SQ/CQ ring sizes
+ CLAMP = 1 << 4,
+ // Attach to existing wq
+ ATTACH_WQ = 1 << 5,
+ // Start with ring disabled
+ R_DISABLED = 1 << 6,
+};
+
+// Parameters for [[setup]]. Partially completed by the kernel.
+export type params = struct {
+ sq_entries: u32,
+ cq_entries: u32,
+ flags: u32,
+ sq_thread_cpu: u32,
+ sq_thread_idle: u32,
+ features: features,
+ wq_fd: u32,
+ resv: [3]u32,
+ sq_off: sqring_offsets,
+ cq_off: cqring_offsets,
+};
+
+// Features supported by the kernel.
+export type features = enum u32 {
+ SINGLE_MMAP = 1 << 0,
+ NODROP = 1 << 1,
+ SUBMIT_STABLE = 1 << 2,
+ RW_CUR_POS = 1 << 3,
+ CUR_PERSONALITY = 1 << 4,
+ FAST_POLL = 1 << 5,
+ POLL_32BITS = 1 << 6,
+};
+
+// Flags for [[enter]].
+export type enter_flags = enum uint {
+ GETEVENTS = 1 << 0,
+ SQ_WAKEUP = 1 << 1,
+ SQ_WAIT = 1 << 2,
+};
+
+// Operations for [[register]].
+export type regop = enum uint {
+ 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,
+};
+
+// Information for a REGISTER_FILES_UPDATE operation.
+export type files_update = struct {
+ offs: u32,
+ resv: u32,
+ // XXX: i32 but aligned to u64
+ fds: u64,
+};
+
+// Flags for a probe operation.
+export type op_flags = enum u16 {
+ SUPPORTED = 1 << 0,
+};
+
+// REGISTER_PROBE operation details.
+export type probe_op = struct {
+ op: u8,
+ resv: u8,
+ flags: op_flags,
+ resv2: u32,
+};
+
+// Summary of REGISTER_PROBE results.
+export type probe = struct {
+ last_op: u8,
+ ops_len: u8,
+ resv: u16,
+ resv2: [3]u32,
+ ops: [*]probe_op,
+};
+
+// Details for a REGISTER_RESTRICTIONS operation.
+export type restriction = struct {
+ opcode: restriction_op,
+ union {
+ register_op: u8,
+ sqe_op: u8,
+ sqe_flags: u8,
+ },
+ resv: u8,
+ resv2: [3]u32,
+};
+
+// Opcode for a [[restriction]].
+export type restriction_op = enum u16 {
+ // Allow an io_uring_register(2) opcode
+ REGISTER_OP = 0,
+ // Allow an sqe opcode
+ SQE_OP = 1,
+ // Allow sqe flags
+ SQE_FLAGS_ALLOWED = 2,
+ // Require sqe flags (these flags must be set on each submission)
+ SQE_FLAGS_REQUIRED = 3,
+};
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -517,6 +517,12 @@ linux() {
gen_ssa linux format::elf
}
+linux_uring() {
+ gen_srcs linux::uring \
+ uring.ha
+ gen_ssa linux::uring
+}
+
linux_vdso() {
gen_srcs linux::vdso \
vdso.ha
@@ -769,6 +775,7 @@ hash_crc64
hash_fnv
io
linux
+linux_uring
linux_vdso
net
net_ip
diff --git a/stdlib.mk b/stdlib.mk
@@ -191,6 +191,9 @@ hare_stdlib_deps+=$(stdlib_io)
stdlib_linux=$(HARECACHE)/linux/linux.o
hare_stdlib_deps+=$(stdlib_linux)
+stdlib_linux_uring=$(HARECACHE)/linux/uring/linux_uring.o
+hare_stdlib_deps+=$(stdlib_linux_uring)
+
stdlib_linux_vdso=$(HARECACHE)/linux/vdso/linux_vdso.o
hare_stdlib_deps+=$(stdlib_linux_vdso)
@@ -693,6 +696,16 @@ $(HARECACHE)/linux/linux.ssa: $(stdlib_linux_srcs) $(stdlib_rt) $(stdlib_format_
@HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nlinux \
-t$(HARECACHE)/linux/linux.td $(stdlib_linux_srcs)
+# linux::uring
+stdlib_linux_uring_srcs= \
+ $(STDLIB)/linux/uring/uring.ha
+
+$(HARECACHE)/linux/uring/linux_uring.ssa: $(stdlib_linux_uring_srcs) $(stdlib_rt)
+ @printf 'HAREC \t$@\n'
+ @mkdir -p $(HARECACHE)/linux/uring
+ @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nlinux::uring \
+ -t$(HARECACHE)/linux/uring/linux_uring.td $(stdlib_linux_uring_srcs)
+
# linux::vdso
stdlib_linux_vdso_srcs= \
$(STDLIB)/linux/vdso/vdso.ha
@@ -1148,6 +1161,9 @@ hare_testlib_deps+=$(testlib_io)
testlib_linux=$(TESTCACHE)/linux/linux.o
hare_testlib_deps+=$(testlib_linux)
+testlib_linux_uring=$(TESTCACHE)/linux/uring/linux_uring.o
+hare_testlib_deps+=$(testlib_linux_uring)
+
testlib_linux_vdso=$(TESTCACHE)/linux/vdso/linux_vdso.o
hare_testlib_deps+=$(testlib_linux_vdso)
@@ -1669,6 +1685,16 @@ $(TESTCACHE)/linux/linux.ssa: $(testlib_linux_srcs) $(testlib_rt) $(testlib_form
@HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nlinux \
-t$(TESTCACHE)/linux/linux.td $(testlib_linux_srcs)
+# linux::uring
+testlib_linux_uring_srcs= \
+ $(STDLIB)/linux/uring/uring.ha
+
+$(TESTCACHE)/linux/uring/linux_uring.ssa: $(testlib_linux_uring_srcs) $(testlib_rt)
+ @printf 'HAREC \t$@\n'
+ @mkdir -p $(TESTCACHE)/linux/uring
+ @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nlinux::uring \
+ -t$(TESTCACHE)/linux/uring/linux_uring.td $(testlib_linux_uring_srcs)
+
# linux::vdso
testlib_linux_vdso_srcs= \
$(STDLIB)/linux/vdso/vdso.ha