From 82f839f8a72563d0ad6cb0caa9ee80fbf6171782 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sat, 15 Oct 2022 14:06:07 -0300 Subject: [PATCH] syscalls: poll --- src/arch/x86_64/syscall.asm | 4 +- src/fs/vfs.c | 13 ++++ src/include/kernel/devman.h | 3 + src/include/kernel/vfs.h | 2 + src/include/poll.h | 21 +++++++ src/sys/devman.c | 10 ++++ src/sys/syscalls/poll.c | 114 ++++++++++++++++++++++++++++++++++++ src/video/consoledev.c | 37 ++++++++++-- 8 files changed, 197 insertions(+), 7 deletions(-) create mode 100644 src/include/poll.h create mode 100644 src/sys/syscalls/poll.c diff --git a/src/arch/x86_64/syscall.asm b/src/arch/x86_64/syscall.asm index 987e91b8..65b62b29 100644 --- a/src/arch/x86_64/syscall.asm +++ b/src/arch/x86_64/syscall.asm @@ -29,7 +29,8 @@ extern syscall_pipe2 extern syscall_mkdir extern syscall_munmap extern syscall_umask -func_count equ 28 +extern syscall_poll +func_count equ 29 func_table: @@ -61,6 +62,7 @@ func_table: dq syscall_mkdir dq syscall_munmap dq syscall_umask + dq syscall_poll section .text global asm_syscall_entry diff --git a/src/fs/vfs.c b/src/fs/vfs.c index 962b77cb..e00e1494 100644 --- a/src/fs/vfs.c +++ b/src/fs/vfs.c @@ -100,6 +100,19 @@ int vfs_isatty(vnode_t* node){ } +int vfs_poll(vnode_t* node, pollfd* fd){ + + switch(GETTYPE(node->st.st_mode)){ + case TYPE_CHARDEV: + case TYPE_BLOCKDEV: + return devman_poll(node->st.st_rdev, fd); + case TYPE_FIFO: + default: + _panic("Unsupported poll", NULL); + } + +} + int vfs_ioctl(vnode_t* node, unsigned long request, void* arg, int* result){ if(GETTYPE(node->st.st_mode) != TYPE_CHARDEV) diff --git a/src/include/kernel/devman.h b/src/include/kernel/devman.h index 8b132dee..a3cfadc7 100644 --- a/src/include/kernel/devman.h +++ b/src/include/kernel/devman.h @@ -2,6 +2,7 @@ #define _DEVMAN_H_INCLUDE #include +#include #define MAJOR_CONSOLE 1 #define MAJOR_ZERO 2 @@ -16,6 +17,7 @@ typedef struct{ int (*isatty)(int minor); int (*isseekable)(int minor, size_t* seekmax); int (*ioctl)(int minor, unsigned long request, void* arg, int* result); + int (*poll)(int minor, pollfd* fd); } devcalls; int devman_read(int *error, int dev, void* buff, size_t count, size_t offset); @@ -24,6 +26,7 @@ int devman_newdevice(char* name, int type, int major, int minor, devcalls* calls int devman_isatty(int dev); int devman_isseekable(int dev, size_t* seekmax); int devman_ioctl(int dev, unsigned long request, void* arg, int* result); +int devman_poll(int dev, pollfd* fd); void devman_init(); #endif diff --git a/src/include/kernel/vfs.h b/src/include/kernel/vfs.h index 61e067d0..95ace7b4 100644 --- a/src/include/kernel/vfs.h +++ b/src/include/kernel/vfs.h @@ -5,6 +5,7 @@ #include #include #include +#include struct _vnode_t; struct _fscalls_t; @@ -74,6 +75,7 @@ int vfs_read(int* error, vnode_t* node, void* buff, size_t count, size_t offset) int vfs_isatty(vnode_t* node); int vfs_getdirent(dirnode_t* node, dent_t* buff, size_t count, uintmax_t offset, size_t* readcount); int vfs_ioctl(vnode_t* node, unsigned long request, void* arg, int* result); +int vfs_poll(vnode_t* node, pollfd* fd); void vfs_init(); dirnode_t* vfs_root(); diff --git a/src/include/poll.h b/src/include/poll.h new file mode 100644 index 00000000..6f9ae9d6 --- /dev/null +++ b/src/include/poll.h @@ -0,0 +1,21 @@ +#ifndef _POLL_H_INCLUDE +#define _POLL_H_INCLUDE + +typedef struct{ + int fd; + short events; + short revents; +} pollfd; + +#define POLLIN 0x0001 +#define POLLPRI 0x0002 +#define POLLOUT 0x0004 +#define POLLERR 0x0008 +#define POLLHUP 0x0010 +#define POLLNVAL 0x0020 +#define POLLRDNORM 0x0040 +#define POLLRDBAND 0x0080 +#define POLLWRNORM 0x0100 +#define POLLRDHUP 0x2000 + +#endif diff --git a/src/sys/devman.c b/src/sys/devman.c index 69806f9c..df649684 100644 --- a/src/sys/devman.c +++ b/src/sys/devman.c @@ -75,6 +75,16 @@ int devman_ioctl(int dev, unsigned long request, void* arg, int* result){ return majorcalls[major(dev)]->ioctl(minor(dev), request, arg, result); } +int devman_poll(int dev, pollfd* fd){ + if(major(dev) > highestmajor) + return ENOTTY; + + if(!majorcalls[major(dev)]->poll) + return ENOTTY; + + return majorcalls[major(dev)]->poll(minor(dev), fd); +} + void devman_init(){ devfs_init(); diff --git a/src/sys/syscalls/poll.c b/src/sys/syscalls/poll.c new file mode 100644 index 00000000..f88a8920 --- /dev/null +++ b/src/sys/syscalls/poll.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include + +#define MAXNFDS 4096 + +syscallret syscall_poll(pollfd *fds, size_t nfds, int timeoutms){ + syscallret retv; + retv.ret = -1; + + if(fds > USER_SPACE_END){ + retv.errno = EFAULT; + return retv; + } + + if(nfds > MAXNFDS){ + retv.errno = EINVAL; + return retv; + } + + + // create the internal list + + pollfd* ilist = alloc(1); + + if(!ilist){ + retv.errno = ENOMEM; + return retv; + } + + for(size_t fd = 0; fd < nfds; ++fd){ + + void* tmp = realloc(ilist,(fd+1)*sizeof(pollfd)); + if(!tmp){ + retv.errno = ENOMEM; + goto ret; + } + + ilist[fd].fd = fds[fd].fd; + ilist[fd].events = fds[fd].events; + } + + // check for events and stuff + + bool eventhappened = false; + + fdtable_t* fdtable = &arch_getcls()->thread->proc->fdtable; + + while(!eventhappened){ + for(uintmax_t i = 0; i < nfds; ++i){ + if(ilist[i].fd < 0 || ilist[i].events == 0) + continue; + + // open fd + + fd_t* fd; + + int err = fd_access(fdtable, &fd, ilist[i].fd); + + if(err){ + ilist[i].revents = POLLNVAL; + eventhappened = true; + continue; + } + + // poll + + if(fd->node){ + if(vfs_poll(fd->node, &ilist[i])) + ilist[i].revents = POLLERR; + } + + if(ilist[i].revents) + eventhappened = true; + + // cleanup + + fd_release(fd); + + } + + // TODO check for signal or timeout + + + } + + // copy results into each fd + + size_t eventcount = 0; + + for(uintmax_t i = 0; i < nfds; ++i){ + + if(ilist[i].fd < 0 || ilist[i].revents == 0) + continue; + + fds[i].revents = ilist[i].revents; + + ++eventcount; + + } + + retv.errno = 0; + retv.ret = eventcount; + + ret: + + if(ilist) + free(ilist); + + return retv; +} diff --git a/src/video/consoledev.c b/src/video/consoledev.c index 2648fba6..ffc31bca 100644 --- a/src/video/consoledev.c +++ b/src/video/consoledev.c @@ -153,10 +153,9 @@ __attribute__((noreturn)) static void console_thread(){ } } else{ // not canon - - if(tty.c_lflag & ECHO) + if(tty.c_lflag & ECHO){ console_write(strbufptr, strbuflen); - + } arch_interrupt_disable(); ringbuffer_write(&input, strbufptr, strbuflen); @@ -204,7 +203,6 @@ static int read(int *error, int dev, void* buff, size_t count, size_t offset){ static int write(int *error, int dev, void* buff, size_t count, size_t offset){ *error = 0; - console_write(buff, count); return count; @@ -226,6 +224,8 @@ typedef struct{ unsigned short ws_ypixel; } winsize; +#include + static int ioctl(int minor, unsigned long req, void* arg){ switch(req){ case TIOCGWINSZ: @@ -248,10 +248,29 @@ static int ioctl(int minor, unsigned long req, void* arg){ } +#include + +static int poll(int minor, pollfd* fd){ + + if((fd->events & POLLIN) && input.write != input.read) + fd->revents |= POLLIN; + + if((fd->events & POLLOUT) && outputlock == 0) + fd->revents |= POLLOUT; + + + return 0; + +} + devcalls calls = { - read, write, isatty, isseekable, ioctl + read, write, isatty, isseekable, ioctl, poll }; +static void callback(struct limine_terminal *terminal, uint64_t type, uint64_t arg1, uint64_t arg2, uint64_t arg3){ + asm("cli;hlt"); +} + void consoledev_init(){ if(devman_newdevice("console", TYPE_CHARDEV, MAJOR_CONSOLE, 0, &calls)) @@ -265,7 +284,13 @@ void consoledev_init(){ if(!thread) _panic("Failed to initialise console thread", 0); - tty.c_lflag = ECHO | ICANON; + tty.c_lflag = ECHO | ICANON | ISIG; + tty.c_cc[VINTR] = 0x03; + tty.ibaud = 38400; + tty.obaud = 38400; + tty.c_cc[VMIN] = 1; + liminetty_setcallback(0, callback); + }