#include "fs/VFS.h" #include "memory/MemoryManager.h" #include "sys/Syscall.h" #include "thread/Scheduler.h" #include Result sys_poll(Registers* regs, SyscallArgs args) { struct pollfd* fds = (struct pollfd*)args[0]; nfds_t nfds = (nfds_t)args[1]; int timeout = (int)args[2]; struct pollfd* kfds = (struct pollfd*)TRY(malloc_impl(nfds * sizeof(pollfd))); auto guard = make_scope_guard([kfds] { free_impl(kfds); }); if (!MemoryManager::copy_from_user(fds, kfds, nfds * sizeof(pollfd))) return err(EFAULT); Vector> inodes; auto* current = Scheduler::current(); for (nfds_t i = 0; i < nfds; i++) { int fd = kfds[i].fd; auto maybe_inode = current->resolve_fd(fd); if (maybe_inode.has_error()) { kfds[i].revents |= POLLNVAL; TRY(inodes.try_append({})); } else TRY(inodes.try_append(maybe_inode.release_value()->description->inode)); } bool infinite = timeout < 0; int fds_with_events; do { fds_with_events = 0; for (nfds_t i = 0; i < nfds; i++) { auto& inode = inodes[i]; if (!inode) continue; if (kfds[i].events & POLLIN && !inode->will_block_if_read()) { fds_with_events++; kfds[i].revents |= POLLIN; } } if (!fds_with_events && (timeout > 0 || infinite)) { kernel_sleep(10); timeout -= (int)current->sleep_ticks_left; if (current->interrupted) { guard.deactivate(); free_impl(kfds); if (current->will_invoke_signal_handler()) return err(EINTR); current->process_pending_signals(regs); return err(EINTR); } continue; } } while (false); MemoryManager::copy_to_user(fds, kfds, nfds * sizeof(pollfd)); return fds_with_events; }