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

@ -106,6 +106,8 @@ fileclose(struct file *f)
if(ff.type == FD_MEMFD)
shm_detach(ff.memfd_seg); // the last mapper frees the pages
else if(ff.type == FD_EVENT)
ev_close(ff.ev);
else if(ff.type == FD_PIPE)
pipeclose(ff.pipe, ff.writable);
else if(ff.type == FD_SOCKET)
@ -144,6 +146,14 @@ filestat(struct file *f, struct stat *st)
iunlock(f->ip);
return 0;
}
// An eventfd, timerfd, signalfd or epoll set: Linux calls these anonymous
// inodes, and fstat succeeds on them with nothing much to say. A program
// that fstat()s every descriptor it is handed should not fail on one.
if(f->type == FD_EVENT){
memset(st, 0, sizeof(*st));
st->nlink = 1;
return 0;
}
return -1;
}
@ -155,6 +165,9 @@ fileread(struct file *f, char *addr, int n)
if(f->readable == 0)
return -1;
if(f->type == FD_EVENT)
return ev_read(f, addr, n);
// A memfd is a file: read() and write() move bytes in and out of the shared
// pages, and the descriptor carries its own offset like any other. mmap is
// what it is usually for, but a descriptor that refuses read() is a surprise
@ -248,6 +261,9 @@ filewrite(struct file *f, char *addr, int n)
if(f->writable == 0)
return -1;
if(f->type == FD_EVENT)
return ev_write(f, addr, n);
if(f->type == FD_MEMFD){
r = memfd_rw(f->memfd_seg, 1, (uint64)addr, f->off, n, 1);
if(r > 0)
@ -326,6 +342,9 @@ filewrite(struct file *f, char *addr, int n)
int
file_poll(struct file *f, int events)
{
if(f->type == FD_EVENT)
return ev_poll(f, events);
if(f->type == FD_PIPE)
return pipe_poll(f->pipe, f->readable, f->writable) &
(events | POLLERR | POLLHUP);