summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-06-27 21:03:33 +0200
committerAnton Kling <anton@kling.gg>2024-06-27 21:03:33 +0200
commit565ef5415437bde9635e8e252e4aa9f503d3ef8d (patch)
treee17efbe78b16f10298c98dce19cb883658a294b3
parente107e3adfcf31fcf25cd441e00cd66990f049493 (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.c75
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 = &current_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);
}