diff options
author | Anton Kling <anton@kling.gg> | 2024-06-27 21:03:33 +0200 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2024-06-27 21:03:33 +0200 |
commit | 565ef5415437bde9635e8e252e4aa9f503d3ef8d (patch) | |
tree | e17efbe78b16f10298c98dce19cb883658a294b3 | |
parent | e107e3adfcf31fcf25cd441e00cd66990f049493 (diff) |
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.
-rw-r--r-- | kernel/poll.c | 75 |
1 files changed, 41 insertions, 34 deletions
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 <interrupts.h> #include <lib/list.h> #include <poll.h> -#include <sched/scheduler.h> -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); } |