]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: EPOLLET edge-triggered epoll mode with smoke test (81/81)
authorTulio A M Mendes <[email protected]>
Mon, 16 Feb 2026 15:49:22 +0000 (12:49 -0300)
committerTulio A M Mendes <[email protected]>
Mon, 16 Feb 2026 15:49:22 +0000 (12:49 -0300)
src/kernel/syscall.c
tests/smoke_test.exp
user/init.c

index df15109746a75e4d17e2d05b4fe1c337487f79aa..cd9ad8382af556029a446b3118172574659fb2eb 100644 (file)
@@ -1055,6 +1055,7 @@ struct epoll_interest {
     int fd;
     uint32_t events;
     uint64_t data;
+    uint32_t last_revents;
 };
 
 struct epoll_instance {
@@ -1136,6 +1137,7 @@ static int syscall_epoll_ctl_impl(int epfd, int op, int fd,
         ep->items[ep->count].fd = fd;
         ep->items[ep->count].events = ev.events;
         ep->items[ep->count].data = ev.data;
+        ep->items[ep->count].last_revents = 0;
         ep->count++;
         return 0;
     }
@@ -1147,6 +1149,7 @@ static int syscall_epoll_ctl_impl(int epfd, int op, int fd,
         if (copy_from_user(&ev, user_event, sizeof(ev)) < 0) return -EFAULT;
         ep->items[idx].events = ev.events;
         ep->items[idx].data = ev.data;
+        ep->items[idx].last_revents = 0;
         return 0;
     }
 
@@ -1212,9 +1215,19 @@ static int syscall_epoll_wait_impl(int epfd, struct epoll_event* user_events,
             if (vfs_rev & VFS_POLL_HUP) revents |= EPOLLHUP;
 
             if (revents) {
-                out[ready].events = revents;
-                out[ready].data = ep->items[i].data;
-                ready++;
+                int report = 1;
+                if (ep->items[i].events & EPOLLET) {
+                    uint32_t new_bits = revents & ~ep->items[i].last_revents;
+                    if (!new_bits) report = 0;
+                }
+                ep->items[i].last_revents = revents;
+                if (report) {
+                    out[ready].events = revents;
+                    out[ready].data = ep->items[i].data;
+                    ready++;
+                }
+            } else {
+                ep->items[i].last_revents = 0;
             }
         }
 
index 2be35e9f30c51dee782611424812ea3ddc73641b..a7f712bb69aa197e52b1196dff07d9a1517d457e 100755 (executable)
@@ -100,6 +100,7 @@ set tests {
     {"poll regfile"         "\\[init\\] poll regfile OK"}
     {"hard link"            "\\[init\\] hard link OK"}
     {"epoll"                "\\[init\\] epoll OK"}
+    {"epollet"              "\\[init\\] epollet OK"}
     {"inotify"              "\\[init\\] inotify OK"}
     {"aio"                  "\\[init\\] aio OK"}
     {"nanosleep"            "\\[init\\] nanosleep OK"}
index 6f5fa593fb74b8e723bded5407fe5fb86da2db71..53f6de8ff3bc7461056c739bd986a192d722a34c 100644 (file)
@@ -184,8 +184,9 @@ struct pollfd {
 };
 
 enum {
-    POLLIN = 0x0001,
+    POLLIN  = 0x0001,
     POLLOUT = 0x0004,
+    EPOLLET = (1U << 31),
 };
 
 enum {
@@ -3256,6 +3257,66 @@ void _start(void) {
         sys_write(1, "[init] epoll OK\n", (uint32_t)(sizeof("[init] epoll OK\n") - 1));
     }
 
+    // C22b: EPOLLET edge-triggered mode
+    {
+        int epfd = sys_epoll_create(1);
+        if (epfd < 0) {
+            sys_write(1, "[init] epollet create failed\n", (uint32_t)(sizeof("[init] epollet create failed\n") - 1));
+            sys_exit(1);
+        }
+
+        int fds[2];
+        if (sys_pipe(fds) < 0) {
+            sys_write(1, "[init] epollet pipe failed\n", (uint32_t)(sizeof("[init] epollet pipe failed\n") - 1));
+            sys_exit(1);
+        }
+
+        struct { uint32_t events; uint32_t data; } ev;
+        ev.events = POLLIN | EPOLLET;
+        ev.data = 42;
+        if (sys_epoll_ctl(epfd, 1, fds[0], &ev) < 0) {
+            sys_write(1, "[init] epollet ctl failed\n", (uint32_t)(sizeof("[init] epollet ctl failed\n") - 1));
+            sys_exit(1);
+        }
+
+        (void)sys_write(fds[1], "X", 1);
+
+        struct { uint32_t events; uint32_t data; } out;
+        int n = sys_epoll_wait(epfd, &out, 1, 0);
+        if (n != 1 || !(out.events & POLLIN)) {
+            sys_write(1, "[init] epollet first wait failed\n", (uint32_t)(sizeof("[init] epollet first wait failed\n") - 1));
+            sys_exit(1);
+        }
+
+        n = sys_epoll_wait(epfd, &out, 1, 0);
+        if (n != 0) {
+            sys_write(1, "[init] epollet second wait should be 0\n", (uint32_t)(sizeof("[init] epollet second wait should be 0\n") - 1));
+            sys_exit(1);
+        }
+
+        char tmp;
+        (void)sys_read(fds[0], &tmp, 1);
+
+        n = sys_epoll_wait(epfd, &out, 1, 0);
+        if (n != 0) {
+            sys_write(1, "[init] epollet post-drain should be 0\n", (uint32_t)(sizeof("[init] epollet post-drain should be 0\n") - 1));
+            sys_exit(1);
+        }
+
+        (void)sys_write(fds[1], "Y", 1);
+
+        n = sys_epoll_wait(epfd, &out, 1, 0);
+        if (n != 1 || !(out.events & POLLIN)) {
+            sys_write(1, "[init] epollet re-arm failed\n", (uint32_t)(sizeof("[init] epollet re-arm failed\n") - 1));
+            sys_exit(1);
+        }
+
+        (void)sys_close(fds[0]);
+        (void)sys_close(fds[1]);
+        (void)sys_close(epfd);
+        sys_write(1, "[init] epollet OK\n", (uint32_t)(sizeof("[init] epollet OK\n") - 1));
+    }
+
     // C23: inotify_init/add_watch/rm_watch smoke
     {
         int ifd = sys_inotify_init();