io.nx
buildroot/runtime/io.nx
about
io.nx -- epoll-based non-blocking event loop (Phase G3).
Research / reference:
Linux epoll (2.5.45, 2002) — the scalable alternative to select
and poll. Watches thousands of fds in O(1) per ready event.
Nginx / redis / node.js all run on this model.
Sovereignty: direct epoll_create1 / epoll_ctl / epoll_wait
syscalls. No libev, no libuv, no glibc epoll wrapper. The same
API works on NishiOS once its equivalent interrupt-dispatched
ready-queue ships.
Pattern for single-threaded server on this loop:
let ep: i64 = io_epoll_new()
io_epoll_add(ep, listen_fd, IO_READ)
let evs: *IoEvent = io_events_alloc(64)
while serving {
let n: i64 = io_wait(ep, evs, 64, -1)
var i: i64 = 0
while i < n {
let e: *IoEvent = io_event_at(evs, i)
handle(e.fd, e.events)
i = i + 1
}
}
Syscalls (Linux RV64):
20 epoll_create1
21 epoll_ctl
22 epoll_pwait
Event masks (subset we support):
EPOLLIN = 0x001 — readable
EPOLLOUT = 0x004 — writable
EPOLLHUP = 0x010 — peer hangup
EPOLLET = 0x80000000 — edge-triggered (uint32 bit 31)
dependencies 1 imports · 0 importers
imports: syscalls.nx
imported by: nobody (leaf or entry point)
structs
| 61 | struct IoEvent { |
consts
| 41 | const SYS_EPOLL_CREATE1: i64 = 20 |
| 42 | const SYS_EPOLL_CTL: i64 = 21 |
| 43 | const SYS_EPOLL_PWAIT: i64 = 22 |
| 45 | const EPOLL_CTL_ADD: i64 = 1 |
| 46 | const EPOLL_CTL_DEL: i64 = 2 |
| 47 | const EPOLL_CTL_MOD: i64 = 3 |
| 49 | const IO_READ: i64 = 0x001 // EPOLLIN |
| 50 | const IO_WRITE: i64 = 0x004 // EPOLLOUT |
| 51 | const IO_HUP: i64 = 0x010 // EPOLLHUP |
| 66 | const IO_EVENT_BYTES: i64 = 16 |
| 128 | const SYS_FCNTL: i64 = 25 |
| 129 | const F_GETFL: i64 = 3 |
| 130 | const F_SETFL: i64 = 4 |
| 131 | const O_NONBLOCK: i64 = 0x800 |
functions
| 70 | func io_epoll_new() -> i64 { |
| 77 | func io_epoll_add(ep: i64, fd: i64, events: i64) -> i64 { |
| 87 | func io_epoll_mod(ep: i64, fd: i64, events: i64) -> i64 { |
| 98 | func io_epoll_del(ep: i64, fd: i64) -> i64 { |
| 104 | func io_events_alloc(n: i64) -> *IoEvent { |
| 109 | func io_event_at(evs: *IoEvent, i: i64) -> *IoEvent { |
| 117 | func io_wait(ep: i64, evs: *IoEvent, max_events: i64, |
| 135 | func io_set_nonblock(fd: i64) -> i64 { |