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:
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 \