summaryrefslogtreecommitdiff
path: root/kernel/poll.c
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2023-10-30 22:12:14 +0100
committerAnton Kling <anton@kling.gg>2023-10-31 00:18:38 +0100
commit8a9208612eec8ddae4c418485d848ecfa0613699 (patch)
tree2f4b29200c2f0c19ae52f45bdb9b38a41b356e30 /kernel/poll.c
parentca76600acc8bf7a02346efa5bd8f17072210ec01 (diff)
Meta: Move kernel and userland to their own folders.
This is to allow both the kernel and the userland to share certain header files and to make the folder structure a bit more clear.
Diffstat (limited to 'kernel/poll.c')
-rw-r--r--kernel/poll.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/kernel/poll.c b/kernel/poll.c
new file mode 100644
index 0000000..5e02723
--- /dev/null
+++ b/kernel/poll.c
@@ -0,0 +1,54 @@
+#include <fs/vfs.h>
+#include <halts.h>
+#include <poll.h>
+#include <sched/scheduler.h>
+
+int poll(struct pollfd *fds, size_t nfds, int timeout) {
+ (void)timeout;
+ int read_locks[nfds];
+ int write_locks[nfds];
+ int disconnect_locks[nfds];
+ for (size_t i = 0; i < nfds; i++) {
+ if (fds[i].fd < 0)
+ continue;
+ vfs_fd_t *f = get_vfs_fd(fds[i].fd);
+ if (fds[i].events & POLLIN)
+ read_locks[i] = create_read_fdhalt(f);
+ if (fds[i].events & POLLOUT)
+ write_locks[i] = create_write_fdhalt(f);
+ if (fds[i].events & POLLHUP)
+ disconnect_locks[i] = create_disconnect_fdhalt(f);
+ }
+
+ switch_task();
+
+ for (size_t i = 0; i < nfds; i++) {
+ if (fds[i].fd < 0)
+ continue;
+ if (fds[i].events & POLLIN)
+ unset_read_fdhalt(read_locks[i]);
+ if (fds[i].events & POLLOUT)
+ unset_write_fdhalt(write_locks[i]);
+ if (fds[i].events & POLLHUP)
+ unset_disconnect_fdhalt(disconnect_locks[i]);
+ }
+ 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);
+ if (!f) {
+ if (fds[i].events & POLLHUP)
+ fds[i].revents |= POLLHUP;
+ } else {
+ if (f->inode->has_data && fds[i].events & POLLIN)
+ fds[i].revents |= POLLIN;
+ if (f->inode->can_write && fds[i].events & POLLOUT)
+ fds[i].revents |= POLLOUT;
+ if (!(f->inode->is_open) && fds[i].events & POLLHUP)
+ fds[i].revents |= POLLHUP;
+ }
+ }
+ return 0;
+}