diff options
author | dzwdz | 2022-04-10 15:13:49 +0200 |
---|---|---|
committer | dzwdz | 2022-04-10 15:13:49 +0200 |
commit | 3e7d1acffd81175246fab1ed8be30569c9cd3289 (patch) | |
tree | 492540543055adb07904e86d17c7304663e16517 | |
parent | 3c9ee975733680d816bb0e5d550f22aaa2f0a73f (diff) |
kernel: idle process
-rw-r--r-- | src/init/main.c | 32 | ||||
-rw-r--r-- | src/kernel/arch/i386/driver/ps2.c | 9 | ||||
-rw-r--r-- | src/kernel/arch/i386/driver/ps2.h | 1 | ||||
-rw-r--r-- | src/kernel/proc.c | 29 | ||||
-rw-r--r-- | src/kernel/proc.h | 8 | ||||
-rw-r--r-- | src/kernel/vfs/request.c | 5 | ||||
-rw-r--r-- | src/kernel/vfs/root.c | 21 |
7 files changed, 75 insertions, 30 deletions
diff --git a/src/init/main.c b/src/init/main.c index f1e1e22..06e48cf 100644 --- a/src/init/main.c +++ b/src/init/main.c @@ -29,7 +29,7 @@ int main(void) { MOUNT("/bind", fs_passthru(NULL)); - if (!_syscall_fork()) { + if (false && !_syscall_fork()) { __stdin = __stdout = _syscall_open(argify("/com1")); if (__stdout < 0) _syscall_exit(1); @@ -37,21 +37,21 @@ int main(void) { _syscall_exit(1); } - /* - * if (!_syscall_fork()) { - * __stdout = _syscall_open(argify("/vga_tty")); - * if (__stdout < 0) _syscall_exit(1); - - * __stdin = _syscall_open(argify("/keyboard")); - * if (__stdin < 0) { - * printf("couldn't open /keyboard\n"); - * _syscall_exit(1); - * } - - * shell_loop(); - * _syscall_exit(1); - * } - */ + + if (!_syscall_fork()) { + __stdout = _syscall_open(argify("/vga_tty")); + if (__stdout < 0) _syscall_exit(1); + + __stdin = _syscall_open(argify("/keyboard")); + if (__stdin < 0) { + printf("couldn't open /keyboard\n"); + _syscall_exit(1); + } + + shell_loop(); + _syscall_exit(1); + } + // try to find any working output __stdout = _syscall_open(argify("/com1")); diff --git a/src/kernel/arch/i386/driver/ps2.c b/src/kernel/arch/i386/driver/ps2.c index 697bd34..5121b9e 100644 --- a/src/kernel/arch/i386/driver/ps2.c +++ b/src/kernel/arch/i386/driver/ps2.c @@ -7,17 +7,16 @@ static volatile uint8_t backlog[BACKLOG_CAPACITY] = {}; static volatile size_t backlog_size = 0; +bool ps2_ready(void) { + return backlog_size > 0; +} + void ps2_recv(uint8_t s) { if (backlog_size >= BACKLOG_CAPACITY) return; backlog[backlog_size++] = s; } size_t ps2_read(uint8_t *buf, size_t len) { - irq_interrupt_flag(true); - while (backlog_size == 0) - asm("hlt" ::: "memory"); - irq_interrupt_flag(false); - if (backlog_size <= len) len = backlog_size; backlog_size -= len; /* guaranteed to never be < 0 */ diff --git a/src/kernel/arch/i386/driver/ps2.h b/src/kernel/arch/i386/driver/ps2.h index 4b56056..712b157 100644 --- a/src/kernel/arch/i386/driver/ps2.h +++ b/src/kernel/arch/i386/driver/ps2.h @@ -3,5 +3,6 @@ #include <stddef.h> #include <stdint.h> +bool ps2_ready(void); void ps2_recv(uint8_t scancode); size_t ps2_read(uint8_t *buf, size_t max_len); diff --git a/src/kernel/proc.c b/src/kernel/proc.c index 2af352b..8e94d24 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -6,6 +6,8 @@ #include <kernel/vfs/mount.h> #include <shared/mem.h> #include <stdint.h> +#include <kernel/arch/i386/interrupts/irq.h> // TODO move irq stuff to arch/generic +#include <kernel/vfs/root.h> // TODO struct process *process_first; struct process *process_current; @@ -66,11 +68,30 @@ void process_switch(struct process *proc) { _Noreturn void process_switch_any(void) { struct process *found = process_find(PS_RUNNING); - if (found) - process_switch(found); + if (found) process_switch(found); + process_idle(); +} + +_Noreturn void process_idle(void) { + struct process *procs[16]; + size_t len = process_find_multiple(PS_WAITS4IRQ, procs, 16); - mem_debugprint(); - cpu_shutdown(); + if (len == 0) { + mem_debugprint(); + cpu_shutdown(); + } + + irq_interrupt_flag(true); + for (;;) { + asm("hlt" ::: "memory"); // TODO move to irq.c + for (size_t i = 0; i < len; i++) { + if (procs[i]->waits4irq.ready()) { + irq_interrupt_flag(false); + vfs_root_handler(&procs[i]->waits4irq.req); // TODO this should be a function pointer too + process_switch_any(); + } + } + } } // TODO there's no check for going past the stack - VULN diff --git a/src/kernel/proc.h b/src/kernel/proc.h index 2066b40..dc7525d 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -11,6 +11,7 @@ enum process_state { PS_WAITS4CHILDDEATH, PS_WAITS4FS, PS_WAITS4REQUEST, + PS_WAITS4IRQ, // set by root vfs }; struct process { @@ -36,6 +37,10 @@ struct process { int max_len; struct fs_wait_response __user *res; } awaited_req; // PS_WAITS4REQUEST + struct { + struct vfs_request req; + bool (*ready)(); + } waits4irq; }; struct vfs_request *handled_req; @@ -56,6 +61,9 @@ struct process *process_fork(struct process *parent); _Noreturn void process_switch(struct process *proc); _Noreturn void process_switch_any(void); // switches to any running process +/** If there are any processes waiting for IRQs, wait with them. Otherwise, shut down */ +_Noreturn void process_idle(void); + struct process *process_find(enum process_state); size_t process_find_multiple(enum process_state, struct process **buf, size_t max); diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index 5b65e52..e8bf147 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -7,7 +7,6 @@ int vfs_request_create(struct vfs_request req_) { struct vfs_request *req; - int ret; process_current->state = PS_WAITS4FS; process_current->waits4fs.queue_next = NULL; @@ -20,9 +19,7 @@ int vfs_request_create(struct vfs_request req_) { switch (req->backend->type) { case VFS_BACK_ROOT: - ret = vfs_root_handler(req); - ret = vfs_request_finish(req, ret); - return ret; + return vfs_root_handler(req); case VFS_BACK_USER: if (req->backend->handler && req->backend->handler->state == PS_WAITS4REQUEST) diff --git a/src/kernel/vfs/root.c b/src/kernel/vfs/root.c index f61096c..89c2b3e 100644 --- a/src/kernel/vfs/root.c +++ b/src/kernel/vfs/root.c @@ -55,7 +55,7 @@ static void req_preprocess(struct vfs_request *req, int max_len) { assert(req->input.len + req->offset <= max_len); } -int vfs_root_handler(struct vfs_request *req) { +static int handle(struct vfs_request *req, bool *ready) { switch (req->type) { case VFSOP_OPEN: if (exacteq(req, "/")) return HANDLE_ROOT; @@ -105,6 +105,16 @@ int vfs_root_handler(struct vfs_request *req) { return iter.prior; } case HANDLE_PS2: { + if (!ps2_ready()) { + *ready = false; + req->caller->state = PS_WAITS4IRQ; + /* not copying any memory, both sides point to the same + * struct. this line's only there so i don't depend on + * struct alignment always staying the same */ + req->caller->waits4irq.req = *req; + req->caller->waits4irq.ready = ps2_ready; + return -1; + } uint8_t buf[16]; size_t len = ps2_read(buf, sizeof buf); virt_cpy_to(req->caller->pages, req->output.buf, buf, len); @@ -163,3 +173,12 @@ int vfs_root_handler(struct vfs_request *req) { default: panic_invalid_state(); } } + +int vfs_root_handler(struct vfs_request *req) { + bool ready = true; + int ret = handle(req, &ready); + if (ready) + return vfs_request_finish(req, ret); + else + return -1; +} |