aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/irq.c13
-rw-r--r--src/orphanage.c13
-rw-r--r--src/timer.c15
-rw-r--r--src/uapi/irq.c2
-rw-r--r--src/uapi/proc.c14
5 files changed, 43 insertions, 14 deletions
diff --git a/src/irq.c b/src/irq.c
index bc9e2de..582a06f 100644
--- a/src/irq.c
+++ b/src/irq.c
@@ -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);
}
/**