From: Tulio A M Mendes Date: Sun, 15 Feb 2026 08:39:03 +0000 (-0300) Subject: test: expand smoke tests to 44 — add epoll, inotify, aio_* coverage X-Git-Url: https://projects.tadryanom.me/docs/static/gitweb.css?a=commitdiff_plain;h=51d4dd169ac06951ddecff8695ed2171c6924e41;p=AdrOS.git test: expand smoke tests to 44 — add epoll, inotify, aio_* coverage --- diff --git a/tests/smoke_test.exp b/tests/smoke_test.exp index a4815f4..0b0e3c2 100755 --- a/tests/smoke_test.exp +++ b/tests/smoke_test.exp @@ -84,6 +84,9 @@ set tests { {"select regfile" "\\[init\\] select regfile OK"} {"poll regfile" "\\[init\\] poll regfile OK"} {"hard link" "\\[init\\] hard link OK"} + {"epoll" "\\[init\\] epoll OK"} + {"inotify" "\\[init\\] inotify OK"} + {"aio" "\\[init\\] aio OK"} } # ---- Poll serial.log for results ---- diff --git a/user/init.c b/user/init.c index da3db77..0a82dd4 100644 --- a/user/init.c +++ b/user/init.c @@ -107,6 +107,19 @@ enum { SYSCALL_SETITIMER = 92, SYSCALL_GETITIMER = 93, SYSCALL_WAITID = 94, + + SYSCALL_EPOLL_CREATE = 112, + SYSCALL_EPOLL_CTL = 113, + SYSCALL_EPOLL_WAIT = 114, + + SYSCALL_INOTIFY_INIT = 115, + SYSCALL_INOTIFY_ADD_WATCH = 116, + SYSCALL_INOTIFY_RM_WATCH = 117, + + SYSCALL_AIO_READ = 121, + SYSCALL_AIO_WRITE = 122, + SYSCALL_AIO_ERROR = 123, + SYSCALL_AIO_RETURN = 124, }; enum { @@ -986,6 +999,125 @@ static int sys_waitid(uint32_t idtype, uint32_t id, void* infop, uint32_t option return __syscall_fix(ret); } +static int sys_epoll_create(int size) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_EPOLL_CREATE), "b"(size) + : "memory" + ); + return __syscall_fix(ret); +} + +static int sys_epoll_ctl(int epfd, int op, int fd, void* event) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_EPOLL_CTL), "b"(epfd), "c"(op), "d"(fd), "S"(event) + : "memory" + ); + return __syscall_fix(ret); +} + +static int sys_epoll_wait(int epfd, void* events, int maxevents, int timeout) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_EPOLL_WAIT), "b"(epfd), "c"(events), "d"(maxevents), "S"(timeout) + : "memory" + ); + return __syscall_fix(ret); +} + +static int sys_inotify_init(void) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_INOTIFY_INIT) + : "memory" + ); + return __syscall_fix(ret); +} + +static int sys_inotify_add_watch(int fd, const char* path, uint32_t mask) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_INOTIFY_ADD_WATCH), "b"(fd), "c"(path), "d"(mask) + : "memory" + ); + return __syscall_fix(ret); +} + +static int sys_inotify_rm_watch(int fd, int wd) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_INOTIFY_RM_WATCH), "b"(fd), "c"(wd) + : "memory" + ); + return __syscall_fix(ret); +} + +struct aiocb { + int aio_fildes; + void* aio_buf; + uint32_t aio_nbytes; + uint32_t aio_offset; + int32_t aio_error; + int32_t aio_return; +}; + +static int sys_aio_read(struct aiocb* cb) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_AIO_READ), "b"(cb) + : "memory" + ); + return __syscall_fix(ret); +} + +static int sys_aio_write(struct aiocb* cb) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_AIO_WRITE), "b"(cb) + : "memory" + ); + return __syscall_fix(ret); +} + +static int sys_aio_error(struct aiocb* cb) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_AIO_ERROR), "b"(cb) + : "memory" + ); + return ret; +} + +static int sys_aio_return(struct aiocb* cb) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_AIO_RETURN), "b"(cb) + : "memory" + ); + return ret; +} + __attribute__((noreturn)) static void sys_exit(int code) { __asm__ volatile( "int $0x80\n" @@ -2928,6 +3060,127 @@ void _start(void) { } } + // C22: epoll_create/ctl/wait smoke + { + int epfd = sys_epoll_create(1); + if (epfd < 0) { + sys_write(1, "[init] epoll_create failed\n", (uint32_t)(sizeof("[init] epoll_create failed\n") - 1)); + sys_exit(1); + } + + int fds[2]; + if (sys_pipe(fds) < 0) { + sys_write(1, "[init] epoll pipe failed\n", (uint32_t)(sizeof("[init] epoll pipe failed\n") - 1)); + sys_exit(1); + } + + struct { uint32_t events; uint32_t data; } ev; + ev.events = POLLIN; + ev.data = (uint32_t)fds[0]; + if (sys_epoll_ctl(epfd, 1, fds[0], &ev) < 0) { + sys_write(1, "[init] epoll_ctl ADD failed\n", (uint32_t)(sizeof("[init] epoll_ctl ADD failed\n") - 1)); + sys_exit(1); + } + + struct { uint32_t events; uint32_t data; } out; + int n = sys_epoll_wait(epfd, &out, 1, 0); + if (n != 0) { + sys_write(1, "[init] epoll_wait expected 0\n", (uint32_t)(sizeof("[init] epoll_wait expected 0\n") - 1)); + sys_exit(1); + } + + (void)sys_write(fds[1], "E", 1); + + n = sys_epoll_wait(epfd, &out, 1, 0); + if (n != 1 || !(out.events & POLLIN)) { + sys_write(1, "[init] epoll_wait expected POLLIN\n", (uint32_t)(sizeof("[init] epoll_wait expected POLLIN\n") - 1)); + sys_exit(1); + } + + (void)sys_close(fds[0]); + (void)sys_close(fds[1]); + (void)sys_close(epfd); + sys_write(1, "[init] epoll OK\n", (uint32_t)(sizeof("[init] epoll OK\n") - 1)); + } + + // C23: inotify_init/add_watch/rm_watch smoke + { + int ifd = sys_inotify_init(); + if (ifd < 0) { + sys_write(1, "[init] inotify_init failed\n", (uint32_t)(sizeof("[init] inotify_init failed\n") - 1)); + sys_exit(1); + } + + int wd = sys_inotify_add_watch(ifd, "/tmp", 0x100); + if (wd < 0) { + sys_write(1, "[init] inotify_add_watch failed\n", (uint32_t)(sizeof("[init] inotify_add_watch failed\n") - 1)); + sys_exit(1); + } + + if (sys_inotify_rm_watch(ifd, wd) < 0) { + sys_write(1, "[init] inotify_rm_watch failed\n", (uint32_t)(sizeof("[init] inotify_rm_watch failed\n") - 1)); + sys_exit(1); + } + + (void)sys_close(ifd); + sys_write(1, "[init] inotify OK\n", (uint32_t)(sizeof("[init] inotify OK\n") - 1)); + } + + // C24: aio_read/aio_write smoke + { + int fd = sys_open("/disk/aiotest", O_CREAT | O_TRUNC); + if (fd < 0) { + sys_write(1, "[init] aio open failed\n", (uint32_t)(sizeof("[init] aio open failed\n") - 1)); + sys_exit(1); + } + + char wbuf[4] = {'A', 'I', 'O', '!'}; + struct aiocb wcb; + wcb.aio_fildes = fd; + wcb.aio_buf = wbuf; + wcb.aio_nbytes = 4; + wcb.aio_offset = 0; + wcb.aio_error = -1; + wcb.aio_return = -1; + if (sys_aio_write(&wcb) < 0) { + sys_write(1, "[init] aio_write failed\n", (uint32_t)(sizeof("[init] aio_write failed\n") - 1)); + sys_exit(1); + } + if (sys_aio_error(&wcb) != 0) { + sys_write(1, "[init] aio_error after write bad\n", (uint32_t)(sizeof("[init] aio_error after write bad\n") - 1)); + sys_exit(1); + } + if (sys_aio_return(&wcb) != 4) { + sys_write(1, "[init] aio_return after write bad\n", (uint32_t)(sizeof("[init] aio_return after write bad\n") - 1)); + sys_exit(1); + } + + char rbuf[4] = {0, 0, 0, 0}; + struct aiocb rcb; + rcb.aio_fildes = fd; + rcb.aio_buf = rbuf; + rcb.aio_nbytes = 4; + rcb.aio_offset = 0; + rcb.aio_error = -1; + rcb.aio_return = -1; + if (sys_aio_read(&rcb) < 0) { + sys_write(1, "[init] aio_read failed\n", (uint32_t)(sizeof("[init] aio_read failed\n") - 1)); + sys_exit(1); + } + if (sys_aio_error(&rcb) != 0 || sys_aio_return(&rcb) != 4) { + sys_write(1, "[init] aio_read result bad\n", (uint32_t)(sizeof("[init] aio_read result bad\n") - 1)); + sys_exit(1); + } + if (rbuf[0] != 'A' || rbuf[1] != 'I' || rbuf[2] != 'O' || rbuf[3] != '!') { + sys_write(1, "[init] aio_read data bad\n", (uint32_t)(sizeof("[init] aio_read data bad\n") - 1)); + sys_exit(1); + } + + (void)sys_close(fd); + (void)sys_unlink("/disk/aiotest"); + sys_write(1, "[init] aio OK\n", (uint32_t)(sizeof("[init] aio OK\n") - 1)); + } + enum { NCHILD = 100 }; int children[NCHILD]; for (int i = 0; i < NCHILD; i++) {