From 565ef5415437bde9635e8e252e4aa9f503d3ef8d Mon Sep 17 00:00:00 2001 From: Anton Kling Date: Thu, 27 Jun 2024 21:03:33 +0200 Subject: Kernel: poll should exit early if events already exist In certain cases there is almost always something to read in which case setting up the list of file descriptors and switching context becomes very expensive. --- kernel/poll.c | 75 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 34 deletions(-) (limited to 'kernel/poll.c') diff --git a/kernel/poll.c b/kernel/poll.c index 4c6e411..3a37baf 100644 --- a/kernel/poll.c +++ b/kernel/poll.c @@ -3,12 +3,49 @@ #include #include #include -#include -int poll(struct pollfd *fds, size_t nfds, int timeout) { - (void)timeout; +static int poll_check(struct pollfd *fds, size_t nfds) { int rc = 0; + for (size_t i = 0; i < nfds; i++) { + fds[i].revents = 0; + if (0 > fds[i].fd) { + continue; + } + vfs_fd_t *f = get_vfs_fd(fds[i].fd, NULL); + if (!f) { + if (fds[i].events & POLLHUP) { + fds[i].revents |= POLLHUP; + } + } else { + if ((fds[i].events & POLLIN) && f->inode->_has_data) { + if (f->inode->_has_data(f->inode)) { + fds[i].revents |= POLLIN; + } + } + if ((fds[i].events & POLLOUT) && f->inode->_can_write) { + if (f->inode->_can_write(f->inode)) { + fds[i].revents |= POLLOUT; + } + } + if ((fds[i].events & POLLHUP) && !(f->inode->is_open)) { + fds[i].revents |= POLLHUP; + } + } + if (fds[i].revents) { + rc++; + } + } + return rc; +} +int poll(struct pollfd *fds, size_t nfds, int timeout) { + (void)timeout; + { + int rc; + if ((rc = poll_check(fds, nfds)) > 0) { + return rc; + } + } disable_interrupts(); struct list *read_list = ¤t_task->read_list; @@ -46,35 +83,5 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) { return -EINTR; } - for (size_t i = 0; i < nfds; i++) { - if (0 > fds[i].fd) { - fds[i].revents = 0; - continue; - } - vfs_fd_t *f = get_vfs_fd(fds[i].fd, NULL); - if (!f) { - if (fds[i].events & POLLHUP) { - fds[i].revents |= POLLHUP; - } - } else { - if (f->inode->_has_data) { - if (f->inode->_has_data(f->inode) && fds[i].events & POLLIN) { - fds[i].revents |= POLLIN; - } - } - if (f->inode->_can_write) { - if (f->inode->_can_write(f->inode) && fds[i].events & POLLOUT) { - fds[i].revents |= POLLOUT; - } - } - if (!(f->inode->is_open) && fds[i].events & POLLHUP) { - fds[i].revents |= POLLHUP; - } - } - if (fds[i].revents) { - rc++; - } - } - enable_interrupts(); - return rc; + return poll_check(fds, nfds); } -- cgit v1.2.3