hare

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

commit 67aeb09b77b99130ffcbe178fe5f9c7c1bf1816b
parent 37b75e9ab17fa380f0b406bc664df1867893c25a
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 20 Oct 2021 11:36:45 +0200

iobus: implement poll

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mcmd/iobus/main.ha | 38++++++++++++++++++++------------------
Miobus/io_uring/ops.ha | 32+++++++++++++++++++++++++++++++-
Mscripts/gen-stdlib | 2+-
Mstdlib.mk | 4++--
4 files changed, 54 insertions(+), 22 deletions(-)

diff --git a/cmd/iobus/main.ha b/cmd/iobus/main.ha @@ -5,36 +5,38 @@ use iobus; use os; use strings; use unix::poll; -use unix::poll::{event}; export fn main() void = { + // TODO: It would be nice to have two iobus instances here, one for us + // (i.e. polling stdin) and one for the user. However, it does not seem + // to be possible to poll an io_uring fd on Linux 5.10. I have written + // to the io_uring mailing list for more information. let bus = iobus::new()!; defer iobus::destroy(bus); - const pollfd = [ - poll::pollfd { - fd = os::stdin_file, - events = event::POLLIN, - ... - }, - poll::pollfd { - fd = iobus::busfile(bus), - events = event::POLLIN, - ... - }, - ]; + const in = iobus::register_file(bus, os::stdin_file); + let poll = iobus::poll(bus, in, poll::event::POLLIN)!; + iobus::enqueue(bus, &poll); fmt::error("> ")!; for (true) { - let events = poll::poll(pollfd, poll::INDEF)!; - if (pollfd[0].revents & event::POLLIN > 0) { + const res = match (iobus::dispatch(bus)) { + case err: iobus::error => + fmt::fatal("Error dispatching bus: {}", + iobus::strerror(err)); + case res: iobus::result => + yield res; + }; + defer iobus::done(bus, res); + + if (iobus::handleof(res) == &poll) { + iobus::endpoll(bus, res)!; if (!readcmd(bus)) { fmt::errorln("exit")!; break; }; - }; - if (pollfd[1].revents & event::POLLIN > 0) { - void; // TODO + poll = iobus::poll(bus, in, poll::event::POLLIN)!; + iobus::enqueue(bus, &poll); }; }; }; diff --git a/iobus/io_uring/ops.ha b/iobus/io_uring/ops.ha @@ -2,7 +2,9 @@ use io; use linux::io_uring; use net::ip; use rt; -// TODO: Seek to de-duplicate some of the SQE prep code +use unix::poll; + +// TODO: Seek to de-duplicate more of the SQE prep code fn getsqe(bus: *bus) (*io_uring::sqe | queuefull) = { match (io_uring::get_sqe(&bus.uring)) { @@ -145,3 +147,31 @@ export fn endaccept(res: result, opts: accept_opts...) (io::file | error) = { }; return file; }; + +// Prepares an asynchronous poll operation for a file. +export fn poll( + bus: *bus, + file: file, + events: poll::event, +) (handle | queuefull) = { + // TODO: Support IORING_POLL_ADD_MULTI + let sqe = getsqe(bus)?; + let flags = io_uring::flags::NONE; + let fd = match (file) { + case file: io::file => + yield file: i32; + case file: registered_file => + flags |= io_uring::flags::FIXED_FILE; + yield file: i32; + }; + io_uring::poll_add(sqe, fd, events: uint, flags); + return handle { sqe = sqe, ... }; +}; + +export fn endpoll(bus: *bus, res: result) (poll::event | error) = { + let handle = handleof(res); + assert(handle.sqe.opcode == io_uring::op::POLL_ADD); + return io_uring::result(res)?: poll::event; +}; + +// TODO: poll_remove diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -578,7 +578,7 @@ iobus_io_uring() { handle.ha \ types.ha \ ops.ha - gen_ssa iobus::io_uring errors io linux::io_uring net::ip + gen_ssa iobus::io_uring errors io linux::io_uring net::ip unix::poll } linux() { diff --git a/stdlib.mk b/stdlib.mk @@ -848,7 +848,7 @@ stdlib_iobus_io_uring_srcs= \ $(STDLIB)/iobus/io_uring/types.ha \ $(STDLIB)/iobus/io_uring/ops.ha -$(HARECACHE)/iobus/io_uring/iobus_io_uring.ssa: $(stdlib_iobus_io_uring_srcs) $(stdlib_rt) $(stdlib_errors) $(stdlib_io) $(stdlib_linux_io_uring) $(stdlib_net_ip) +$(HARECACHE)/iobus/io_uring/iobus_io_uring.ssa: $(stdlib_iobus_io_uring_srcs) $(stdlib_rt) $(stdlib_errors) $(stdlib_io) $(stdlib_linux_io_uring) $(stdlib_net_ip) $(stdlib_unix_poll) @printf 'HAREC \t$@\n' @mkdir -p $(HARECACHE)/iobus/io_uring @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Niobus::io_uring \ @@ -2122,7 +2122,7 @@ testlib_iobus_io_uring_srcs= \ $(STDLIB)/iobus/io_uring/types.ha \ $(STDLIB)/iobus/io_uring/ops.ha -$(TESTCACHE)/iobus/io_uring/iobus_io_uring.ssa: $(testlib_iobus_io_uring_srcs) $(testlib_rt) $(testlib_errors) $(testlib_io) $(testlib_linux_io_uring) $(testlib_net_ip) +$(TESTCACHE)/iobus/io_uring/iobus_io_uring.ssa: $(testlib_iobus_io_uring_srcs) $(testlib_rt) $(testlib_errors) $(testlib_io) $(testlib_linux_io_uring) $(testlib_net_ip) $(testlib_unix_poll) @printf 'HAREC \t$@\n' @mkdir -p $(TESTCACHE)/iobus/io_uring @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Niobus::io_uring \