epoll, eventfd, timerfd, signalfd

The set libwayland's event loop is made of, in kernel/sys/sys_event.c:
four kinds of descriptor with no inode, FD_EVENT, that read() drains
and poll() reports on. They were table entries returning ENOSYS that
read as done.

epoll registers (descriptor, file) pairs, so a closed descriptor
leaves the set; level- and edge-triggered, EPOLLONESHOT. Waiting is
poll()'s, a tick at a time. The old eventfd and signalfd numbers (284,
282) were aliased to the new calls and read flags from a garbage
register; they are their own entries now, with epoll_create and
epoll_pwait.

cmd/evtest checks each, then all four in one set. The plans are
brought up to date: everything Wayland was waiting on is built except
setsockopt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-24 10:59:52 +02:00
commit a4fbdb7437
12 changed files with 974 additions and 37 deletions

View file

@ -37,10 +37,10 @@ same lie in a new place.
---
## The five items
## The six items
In dependency order. The first three are what Wayland cannot start without.
Item 1 is built; items 2 and 3 are what a buffer still cannot cross on.
All but item 4 are built.
### 1. `sendmsg` / `recvmsg` with `SCM_RIGHTS` — **done**
@ -128,13 +128,41 @@ strength of the lie.
Small, and grouped here because it is in the same file as item 3 and will be
found by the same testing.
### 5. Dynamic linking
### 5. Dynamic linking — **done**
`PT_INTERP` and `ET_DYN` in `kernel/fs/exec.c`.
`PT_INTERP` and `ET_DYN` in `kernel/fs/exec.c`. A program that names an
interpreter gets it loaded at the bottom of the mmap area and started instead,
with `AT_PHDR`, `AT_PHENT`, `AT_PHNUM`, `AT_BASE` and `AT_ENTRY` to find the
program by; a PIE program is placed where a fixed one would be. The interpreter
is musl's own: `ports/musl` now builds `libc.so` as well, shipped as
`/lib/ld-musl-x86_64.so.1`, which is libc and loader in one file.
**Deferrable, and deferred.** Static binaries are enough to reach a working
desktop with software rendering. This becomes necessary when Mesa does — EGL
means `dlopen` means a loader — and that is a separate decision made later.
The kernel half that was missing besides `exec` was `mmap(MAP_FIXED)` of a
file. It handed back zeroed pages whatever the descriptor said, and kept no
record of them for `fork` — and a dynamic linker maps every library segment
after the first exactly that way.
Every port still links `-static`, on purpose: this makes the other kind
possible, it does not convert anything. `cmd/dynhello` is the test — a
program against `libc.so` and a library of its own, checking TLS, the heap and
a forked child that still has its libraries.
`mprotect` is accepted and not enforced, so RELRO is not read-only yet.
### 6. The event descriptors — **done**
`epoll`, `eventfd`, `timerfd` and `signalfd`, in `kernel/sys/sys_event.c`.
libwayland's event loop is all four in one epoll set, which is why they arrive
together; not in the original list because they were stubs that looked like
syscalls, returning `ENOSYS` from `table.inc` entries that read as done.
They wait the way `poll()` does, a tick at a time, so the latency is 10 ms.
`cmd/evtest` checks each one, then all four in one set, level- and
edge-triggered.
Building it found a signal bug: a default-fatal signal killed on arrival even
when it was blocked. A blocked signal now stays pending, which is the contract
`signalfd` is built on.
---