diff options
author | Marvin Borner | 2021-06-19 13:12:34 +0200 |
---|---|---|
committer | Marvin Borner | 2021-06-19 13:12:34 +0200 |
commit | 73a55007a44d23be40be681c4882fd6ad1e30b60 (patch) | |
tree | 87f37dff42d8ae51dbb2250f1752a03081298cc3 /kernel | |
parent | 02a0c882275959c0fbd58754418ecc1218821e76 (diff) |
Improved bus and device management
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/features/bus.c | 42 | ||||
-rw-r--r-- | kernel/features/dev.c | 14 | ||||
-rw-r--r-- | kernel/features/proc.c | 2 | ||||
-rw-r--r-- | kernel/features/syscall.c | 7 | ||||
-rw-r--r-- | kernel/inc/dev.h | 1 | ||||
-rw-r--r-- | kernel/inc/proc.h | 2 |
6 files changed, 43 insertions, 25 deletions
diff --git a/kernel/features/bus.c b/kernel/features/bus.c index ad7352f..811ad88 100644 --- a/kernel/features/bus.c +++ b/kernel/features/bus.c @@ -93,6 +93,21 @@ static void bus_add_conn(u32 hash, u32 conn) list_add(bus_conns, bus_conn); } +static res bus_conn_ready(struct bus_conn *bus_conn) +{ + struct bus *bus = bus_find_bus(bus_conn->bus); + if (!bus) + return -ENOENT; + + u8 ready = 0; + if (bus->pid == proc_current()->pid) + ready = !stack_empty(bus_conn->in); + else + ready = !stack_empty(bus_conn->out); + + return ready ? EOK : -EAGAIN; +} + static res bus_register(const char *name) { if (!memory_readable(name)) @@ -236,14 +251,14 @@ static res bus_receive(void *buf, u32 offset, u32 count) struct node *iterator = bus_conns->head; while (iterator) { struct bus_conn *sub_bus = iterator->data; - if (sub_bus->bus == bus_owner->hash) + if (sub_bus->bus == bus_owner->hash && bus_conn_ready(sub_bus) == EOK) return bus_conn_receive(sub_bus, buf, offset, count); iterator = iterator->next; } } - if (bus_conn) + if (bus_conn && bus_conn_ready(bus_conn) == EOK) return bus_conn_receive(bus_conn, buf, offset, count); return -EAGAIN; @@ -286,21 +301,6 @@ static res bus_read(void *buf, u32 offset, u32 count) return bus_receive(buf, offset, count); } -static res bus_conn_ready(struct bus_conn *bus_conn) -{ - struct bus *bus = bus_find_bus(bus_conn->bus); - if (!bus) - return -ENOENT; - - u8 ready = 0; - if (bus->pid == proc_current()->pid) - ready = !stack_empty(bus_conn->in); - else - ready = !stack_empty(bus_conn->out); - - return ready ? EOK : -EAGAIN; -} - static res bus_ready(void) { struct bus *bus_owner = bus_find_owner(proc_current()->pid); @@ -312,15 +312,15 @@ static res bus_ready(void) struct node *iterator = bus_conns->head; while (iterator) { struct bus_conn *sub_bus = iterator->data; - if (sub_bus->bus == bus_owner->hash) - return bus_conn_ready(sub_bus); + if (sub_bus->bus == bus_owner->hash && bus_conn_ready(sub_bus) == EOK) + return EOK; iterator = iterator->next; } } - if (bus_conn) - return bus_conn_ready(bus_conn); + if (bus_conn && bus_conn_ready(bus_conn) == EOK) + return EOK; return -EAGAIN; } diff --git a/kernel/features/dev.c b/kernel/features/dev.c index ecc3f0c..0e082f9 100644 --- a/kernel/features/dev.c +++ b/kernel/features/dev.c @@ -63,6 +63,20 @@ static void dev_remove_group(u32 group) group_id--; } +void dev_remove_proc(struct proc *proc) +{ + for (u32 dev = DEV_MIN; dev < DEV_MAX; dev++) { + struct node *iterator = dev_listeners[dev]->head; + while (iterator) { + struct dev_listener *listener = iterator->data; + struct node *next = iterator->next; + if (listener->proc == proc) + list_remove(dev_listeners[dev], iterator); + iterator = next; + } + } +} + CLEAR void dev_add(enum dev_type type, struct dev_dev *dev) { assert(dev_type_valid(type) && !dev_mappings[type]); diff --git a/kernel/features/proc.c b/kernel/features/proc.c index 70e3666..03f45c9 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -1,6 +1,7 @@ // MIT License, Copyright (c) 2020 Marvin Borner #include <assert.h> +#include <dev.h> #include <drivers/cpu.h> #include <drivers/gdt.h> #include <drivers/timer.h> @@ -190,6 +191,7 @@ void proc_exit(s32 status) printf("Process didn't leak memory!\n"); } + dev_remove_proc(proc); stack_destroy(proc->messages); list_destroy(proc->memory); // TODO: Decrement memory ref links virtual_destroy_dir(proc->page_dir); diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index 997fa96..16a83d6 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -63,10 +63,11 @@ static u32 syscall_handler(u32 esp) break; } case SYS_DEV_READ: { - res ready = dev_ready(frame->ebx); - if (ready == -EAGAIN) { + // TODO: This could be done more elegant (e.g. with better bus design) + res ready; + while ((ready = dev_ready(frame->ebx)) == -EAGAIN) dev_block(frame->ebx, proc_current()); - } else if (ready != EOK) { + if (ready != EOK) { frame->eax = ready; break; } diff --git a/kernel/inc/dev.h b/kernel/inc/dev.h index fc5e424..c824009 100644 --- a/kernel/inc/dev.h +++ b/kernel/inc/dev.h @@ -17,6 +17,7 @@ struct dev_dev { void dev_install(void); void dev_add(enum dev_type type, struct dev_dev *dev) NONNULL; +void dev_remove_proc(struct proc *proc) NONNULL; // No NONNULL on syscalls res dev_control(enum dev_type type, u32 request, void *arg1, void *arg2, void *arg3); diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h index b2e5c8b..42ff75d 100644 --- a/kernel/inc/proc.h +++ b/kernel/inc/proc.h @@ -66,7 +66,7 @@ void proc_set_quantum(struct proc *proc, u32 value) NONNULL; void proc_reset_quantum(struct proc *proc) NONNULL; void proc_state(struct proc *proc, enum proc_state state) NONNULL; struct proc *proc_make(enum proc_priv priv); -void proc_make_regs(struct proc *proc); +void proc_make_regs(struct proc *proc) NONNULL; void proc_stack_user_push(struct proc *proc, const void *data, u32 size) NONNULL; void proc_stack_kernel_push(struct proc *proc, const void *data, u32 size) NONNULL; |