From af06d5edc12b452c54c5f3f3f34035c364c1196c Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 23 Jan 2019 08:03:31 +0100 Subject: [PATCH] Kernel: Implement a limited version of POSIX poll(). --- Kernel/Process.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index f17419ed86e..e312edb7c53 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1982,7 +1982,10 @@ int Process::sys$select(const Syscall::SC_select_params* params) memset(readfds, 0, sizeof(fd_set)); auto bitmap = Bitmap::wrap((byte*)readfds, FD_SETSIZE); for (int fd : m_select_read_fds) { - if (m_fds[fd].descriptor->can_read(*this)) { + auto* descriptor = file_descriptor(fd); + if (!descriptor) + continue; + if (descriptor->can_read(*this)) { bitmap.set(fd, true); ++markedfds; } @@ -1993,7 +1996,10 @@ int Process::sys$select(const Syscall::SC_select_params* params) memset(writefds, 0, sizeof(fd_set)); auto bitmap = Bitmap::wrap((byte*)writefds, FD_SETSIZE); for (int fd : m_select_write_fds) { - if (m_fds[fd].descriptor->can_write(*this)) { + auto* descriptor = file_descriptor(fd); + if (!descriptor) + continue; + if (descriptor->can_write(*this)) { bitmap.set(fd, true); ++markedfds; } @@ -2007,7 +2013,41 @@ int Process::sys$poll(pollfd* fds, int nfds, int timeout) { if (!validate_read_typed(fds)) return -EFAULT; - return 0; + + m_select_write_fds.clear_with_capacity(); + m_select_read_fds.clear_with_capacity(); + for (int i = 0; i < nfds; ++i) { + if (fds[i].events & POLLIN) + m_select_read_fds.append(fds[i].fd); + if (fds[i].events & POLLOUT) + m_select_write_fds.append(fds[i].fd); + } + + if (!m_wakeup_requested && timeout < 0) { + block(BlockedSelect); + Scheduler::yield(); + } + m_wakeup_requested = false; + + int fds_with_revents = 0; + + for (int i = 0; i < nfds; ++i) { + auto* descriptor = file_descriptor(fds[i].fd); + if (!descriptor) { + fds[i].revents = POLLNVAL; + continue; + } + fds[i].revents = 0; + if (fds[i].events & POLLIN && descriptor->can_read(*this)) + fds[i].revents |= POLLIN; + if (fds[i].events & POLLOUT && descriptor->can_write(*this)) + fds[i].revents |= POLLOUT; + + if (fds[i].revents) + ++fds_with_revents; + } + + return fds_with_revents; } Inode* Process::cwd_inode()