syscalls: poll

This commit is contained in:
Matheus
2022-10-15 14:06:07 -03:00
parent d66ff03141
commit 82f839f8a7
8 changed files with 197 additions and 7 deletions
+3 -1
View File
@@ -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
+13
View File
@@ -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)
+3
View File
@@ -2,6 +2,7 @@
#define _DEVMAN_H_INCLUDE
#include <sys/stat.h>
#include <poll.h>
#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
+2
View File
@@ -5,6 +5,7 @@
#include <hashtable.h>
#include <errno.h>
#include <dirent.h>
#include <poll.h>
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();
+21
View File
@@ -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
+10
View File
@@ -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();
+114
View File
@@ -0,0 +1,114 @@
#include <kernel/syscalls.h>
#include <kernel/alloc.h>
#include <kernel/vmm.h>
#include <arch/cls.h>
#include <poll.h>
#include <kernel/sched.h>
#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;
}
+31 -6
View File
@@ -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 <arch/cls.h>
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 <poll.h>
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);
}