hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit b6b934c717f9474d0a67104172eb42c270dd77a0
parent 7ae6b0dfbe7000bd87aa0835a8658328b4f2677d
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu, 13 May 2021 20:20:43 -1000

linux::uring: initial commit

Diffstat:
Alinux/uring/uring.ha | 289++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mscripts/gen-stdlib | 7+++++++
Mstdlib.mk | 26++++++++++++++++++++++++++
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