summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/init/main.c32
-rw-r--r--src/kernel/arch/i386/driver/ps2.c9
-rw-r--r--src/kernel/arch/i386/driver/ps2.h1
-rw-r--r--src/kernel/proc.c29
-rw-r--r--src/kernel/proc.h8
-rw-r--r--src/kernel/vfs/request.c5
-rw-r--r--src/kernel/vfs/root.c21
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;
+}