diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-07-08 17:38:59 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-07-08 17:38:59 +0300 |
| commit | 7e828ec1e1479ff9a8afe845539d08ca0dfada5f (patch) | |
| tree | a227c58b30c99058fc10ff3caffeebca7dbd5913 /src | |
| parent | 219c27d420fe0abe5515cefc2513c6fe60aafdf9 (diff) | |
| download | kmi-7e828ec1e1479ff9a8afe845539d08ca0dfada5f.tar.gz kmi-7e828ec1e1479ff9a8afe845539d08ca0dfada5f.zip | |
add orphan checking to timer and irq handling
Diffstat (limited to 'src')
| -rw-r--r-- | src/irq.c | 13 | ||||
| -rw-r--r-- | src/orphanage.c | 13 | ||||
| -rw-r--r-- | src/timer.c | 15 | ||||
| -rw-r--r-- | src/uapi/irq.c | 2 | ||||
| -rw-r--r-- | src/uapi/proc.c | 14 |
5 files changed, 43 insertions, 14 deletions
@@ -7,6 +7,7 @@ */ #include <kmi/irq.h> +#include <kmi/bkl.h> #include <kmi/pmem.h> #include <kmi/debug.h> #include <kmi/assert.h> @@ -54,6 +55,8 @@ stat_t unregister_irq(struct tcb *t, irq_t id) void handle_irq() { + bkl_lock(); + irq_t id = get_irq(); assert(id < max_irq); @@ -65,14 +68,18 @@ void handle_irq() } struct tcb *t = get_tcb(tid); - if (!t) { - error("tcb %llu dead at irq %llu\n", + if (!t || orphan(t)) { + info("tcb %llu dead at irq %llu\n", (unsigned long long)tid, (unsigned long long)id); + + /* unregister irq handler */ + irq_map[id] = 0; + bkl_unlock(); return; } disable_irqs(); notify(t, NOTIFY_IRQ); - error("misc error when trying to notify irq"); + bkl_unlock(); } diff --git a/src/orphanage.c b/src/orphanage.c index e613e8b..3ca016e 100644 --- a/src/orphanage.c +++ b/src/orphanage.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: copyleft-next-0.3.1 */ /* Copyright 2024, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ +#include <kmi/bkl.h> #include <kmi/assert.h> #include <kmi/orphanage.h> @@ -30,6 +31,7 @@ void unorphanize(struct tcb *t) struct tcb *init = get_tcb(1); reference_proc(init); + id_t old_rid = t->rid; t->rid = 1; t->pid = 1; t->eid = 1; @@ -41,15 +43,18 @@ void unorphanize(struct tcb *t) use_vmem(t->proc.vmem); alloc_stack(t); - clear_bits(t->state, TCB_ORPHAN); - assert(init->callback); - set_args3(t, 0, SYS_USER_ORPHANED, t->tid); + set_args4(t, 0, t->tid, SYS_USER_ORPHANED, old_rid); set_return(t, init->callback); t->callback = init->callback; - /** @todo release irqs, here or later? */ + /** @todo release irqs, here or later? Currently leaning towards later + * as they don't really take up any resources and the implementation + * doesn't make it too easy to search for a specific owner, we can just + * discard the IRQ if it turns out that the owner has been orphaned by + * that point. */ + bkl_unlock(); ret_userspace_fast(); unreachable(); } diff --git a/src/timer.c b/src/timer.c index 2d4ff01..573ed7b 100644 --- a/src/timer.c +++ b/src/timer.c @@ -16,14 +16,15 @@ */ #include <kmi/sp_tree.h> -#include <arch/timer.h> #include <kmi/string.h> #include <kmi/notify.h> #include <kmi/nodes.h> #include <kmi/utils.h> -#include <kmi/bkl.h> #include <kmi/timer.h> #include <kmi/debug.h> +#include <kmi/bkl.h> + +#include <arch/timer.h> #include <arch/cpu.h> /** Timer resolution. */ @@ -185,7 +186,7 @@ stat_t remove_timer(struct timer *t) struct sp_node *n = &timer_node_container(t)->sp_n; sp_remove(&sp_root(__cpu_timers()), n); - + free_node(&node_root, t); return OK; } @@ -198,12 +199,16 @@ ticks_t nsecs_to_ticks(tunit_t nsecs) /* call to this function from exception handlers */ void handle_timer() { + /** @todo should this also disable irqs? */ bkl_lock(); struct timer *t = newest_timer(); + id_t tid = t->tid; remove_timer(t); - struct tcb *r = get_tcb(t->tid); - if (!r) { + struct tcb *r = get_tcb(tid); + if (!r || orphan(r)) { + info("tcb %llu dead at timer\n", + (unsigned long long)tid); bkl_unlock(); return; } diff --git a/src/uapi/irq.c b/src/uapi/irq.c index 29da614..9f3931c 100644 --- a/src/uapi/irq.c +++ b/src/uapi/irq.c @@ -22,7 +22,7 @@ SYSCALL_DEFINE1(irq_req)(struct tcb *t, sys_arg_t id) if (!has_cap(t->caps, CAP_IRQ)) return_args1(t, ERR_PERM); - if (!t->callback) + if (!t->callback || !t->notify_id) return_args1(t, ERR_NF); return_args1(t, register_irq(t, id)); diff --git a/src/uapi/proc.c b/src/uapi/proc.c index 293a01f..eddbab8 100644 --- a/src/uapi/proc.c +++ b/src/uapi/proc.c @@ -11,6 +11,7 @@ #include <kmi/proc.h> #include <kmi/bits.h> #include <kmi/power.h> +#include <kmi/assert.h> #include <kmi/notify.h> #include <kmi/orphanage.h> #include <kmi/regions.h> @@ -127,7 +128,18 @@ SYSCALL_DEFINE2(exec)(struct tcb *t, sys_arg_t bin, sys_arg_t interp) if (interp) clear_bit(b->flags, MR_KEEP); - return_args1(t, prepare_proc(t, bin, interp)); + /* should hopefully never actually fail, but if it does, we don't really + * have any choice but to kill the thread. */ + if (prepare_proc(t, bin, interp)) { + /* this kills the thread */ + orphanize(t); + unorphanize(t); + /* should never be reached as we control the thread so we should + * be able to directly jump to pid 1 */ + assert(false); + } + + return_args4(t, 0, t->tid, SYS_USER_SPAWNED, t->pid); } /** |
