diff options
author | Marvin Borner | 2021-04-16 23:22:02 +0200 |
---|---|---|
committer | Marvin Borner | 2021-04-16 23:22:02 +0200 |
commit | 7485f7e441ca892876d9401380aa77610eb85f76 (patch) | |
tree | 065f910effe33f5c9d71cd9619dd25216282a13d /kernel/features | |
parent | 4d4e784770b576199b18f22100689125a18bfd9a (diff) |
New elegant I/O blocking solution
This is done using an internal scheduler syscall (127).
Very nice!
Diffstat (limited to 'kernel/features')
-rw-r--r-- | kernel/features/fs.c | 22 | ||||
-rw-r--r-- | kernel/features/io.c | 28 | ||||
-rw-r--r-- | kernel/features/mm.c | 9 | ||||
-rw-r--r-- | kernel/features/proc.c | 6 | ||||
-rw-r--r-- | kernel/features/syscall.c | 32 |
5 files changed, 50 insertions, 47 deletions
diff --git a/kernel/features/fs.c b/kernel/features/fs.c index c3d5402..34c70e8 100644 --- a/kernel/features/fs.c +++ b/kernel/features/fs.c @@ -198,28 +198,6 @@ res vfs_write(const char *path, void *buf, u32 offset, u32 count) return m->dev->vfs->write(path, buf, offset, count, m->dev); } -res vfs_ioctl(const char *path, u32 request, void *arg1, void *arg2, void *arg3) -{ - if (!memory_readable(path)) - return -EFAULT; - - struct mount_info *m = vfs_find_mount_info(path); - if (!m || !m->dev || !m->dev->vfs) - return -ENOENT; - - if (!m->dev->vfs->ioctl || !m->dev->vfs->perm) - return -EINVAL; - - u32 len = strlen(m->path); - if (len > 1) - path += len; - - if (m->dev->vfs->perm(path, VFS_WRITE, m->dev) != EOK && !proc_super()) - return -EACCES; - - return m->dev->vfs->ioctl(path, request, arg1, arg2, arg3, m->dev); -} - res vfs_stat(const char *path, struct stat *buf) { if (!memory_readable(path)) diff --git a/kernel/features/io.c b/kernel/features/io.c index 6042818..d0f1b1c 100644 --- a/kernel/features/io.c +++ b/kernel/features/io.c @@ -11,6 +11,7 @@ #include <ps2.h> #include <rand.h> #include <str.h> +#include <syscall.h> #include <timer.h> PROTECTED static struct io_dev *io_mappings[IO_MAX] = { 0 }; @@ -40,6 +41,7 @@ res io_poll(u32 *devs) if (!memory_readable(devs)) return -EFAULT; + io_block(IO_BUS, proc_current()); // TODO! for (u32 *p = devs; p && memory_readable(p) && *p; p++) { if (!io_get(*p)) return -ENOENT; @@ -84,30 +86,32 @@ res io_read(enum io_type io, void *buf, u32 offset, u32 count) return dev->read(buf, offset, count); } -void io_block(enum io_type io, struct proc *proc, struct regs *r) +res io_ready(enum io_type io) +{ + struct io_dev *dev; + if (!(dev = io_get(io))) + return -ENOENT; + + if (dev->ready && !dev->ready()) + return -EAGAIN; + + return EOK; +} + +void io_block(enum io_type io, struct proc *proc) { - assert(r->eax == SYS_IOREAD); assert(io_type_valid(io)); list_add(io_listeners[io], proc); proc_state(proc_current(), PROC_BLOCKED); - proc_yield(r); + proc_yield(); } void io_unblock(enum io_type io) { - struct page_dir *dir_bak; - memory_backup_dir(&dir_bak); - assert(io_type_valid(io)); struct node *iterator = io_listeners[io]->head; while (iterator) { struct proc *proc = iterator->data; - struct regs *r = &proc->regs; - - memory_switch_dir(proc->page_dir); - r->eax = io_read(r->ebx, (void *)r->ecx, r->edx, r->esi); - memory_switch_dir(dir_bak); - proc_state(proc, PROC_RUNNING); struct node *next = iterator->next; list_remove(io_listeners[io], iterator); diff --git a/kernel/features/mm.c b/kernel/features/mm.c index d9e4577..9f0bd07 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -602,11 +602,17 @@ void memory_bypass_disable(void) u8 memory_is_user(const void *addr) { + if (!addr) + return 0; + return PDI((u32)addr) >= PAGE_KERNEL_COUNT; } u8 memory_readable(const void *addr) { + if (!addr) + return 0; + struct proc *proc = proc_current(); if (proc && !memory_bypass_validity) return memory_is_user(addr) && virtual_user_readable(proc->page_dir, (u32)addr); @@ -616,6 +622,9 @@ u8 memory_readable(const void *addr) u8 memory_writable(const void *addr) { + if (!addr) + return 0; + struct proc *proc = proc_current(); if (proc && !memory_bypass_validity) return memory_is_user(addr) && virtual_user_writable(proc->page_dir, (u32)addr); diff --git a/kernel/features/proc.c b/kernel/features/proc.c index 6ddeb32..c972f1b 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -177,13 +177,13 @@ void proc_exit(struct proc *proc, struct regs *r, s32 status) free(proc); - proc_yield(r); + proc_yield(); } -void proc_yield(struct regs *r) +void proc_yield(void) { proc_reset_quantum(PROC(current)); - scheduler(r); + __asm__ volatile("int $127"); } struct proc *proc_make(enum proc_priv priv) diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index 2c30a3b..94ea778 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -19,7 +19,6 @@ static void syscall_handler(struct regs *r) { enum sys num = r->eax; - r->eax = EOK; /* printf("[SYSCALL] %d from %s\n", num, proc_current()->name); */ @@ -56,16 +55,18 @@ static void syscall_handler(struct regs *r) // I/O operations case SYS_IOPOLL: { - r->eax = io_poll((u32 *)r->ebx); + r->eax = io_poll((void *)r->ebx); break; } case SYS_IOREAD: { - res ret = io_read(r->ebx, (void *)r->ecx, r->edx, r->esi); - if (ret == -EAGAIN) { - io_block(r->ebx, proc_current(), r); - } else { - r->eax = ret; + res ready = io_ready(r->ebx); + if (ready == -EAGAIN) { + io_block(r->ebx, proc_current()); + } else if (ready != EOK) { + r->eax = ready; + break; } + r->eax = io_read(r->ebx, (void *)r->ecx, r->edx, r->esi); break; } case SYS_IOWRITE: { @@ -87,7 +88,7 @@ static void syscall_handler(struct regs *r) } else { // TODO: Reimplement argc,argv proc_stack_push(proc, 0); - proc_yield(r); + proc_yield(); } break; } @@ -98,7 +99,7 @@ static void syscall_handler(struct regs *r) } case SYS_YIELD: { r->eax = EOK; - proc_yield(r); + proc_yield(); break; } @@ -140,8 +141,19 @@ static void syscall_handler(struct regs *r) } } +// For kernel syscalls (internal) +static void syscall_special_handler(struct regs *r) +{ + if (RING(r) != 0) + return; + + scheduler(r); +} + CLEAR void syscall_init(void) { - idt_set_gate(0x80, (u32)isr128, 0x08, 0x8E); + idt_set_gate(0x7f, (u32)isr127, 0x08, 0x8e); + idt_set_gate(0x80, (u32)isr128, 0x08, 0xee); + isr_install_handler(0x7f, syscall_special_handler); isr_install_handler(0x80, syscall_handler); } |