aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMarvin Borner2021-06-19 13:12:34 +0200
committerMarvin Borner2021-06-19 13:12:34 +0200
commit73a55007a44d23be40be681c4882fd6ad1e30b60 (patch)
tree87f37dff42d8ae51dbb2250f1752a03081298cc3 /kernel
parent02a0c882275959c0fbd58754418ecc1218821e76 (diff)
Improved bus and device management
Diffstat (limited to 'kernel')
-rw-r--r--kernel/features/bus.c42
-rw-r--r--kernel/features/dev.c14
-rw-r--r--kernel/features/proc.c2
-rw-r--r--kernel/features/syscall.c7
-rw-r--r--kernel/inc/dev.h1
-rw-r--r--kernel/inc/proc.h2
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;