aboutsummaryrefslogtreecommitdiff
path: root/src/uapi
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-07-04 22:52:47 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-07-04 22:52:47 +0300
commitfdbc5adf83741d7e3af0c3f0ffdb59bdf42493b6 (patch)
tree2eb538b9ecc2898d1f94305fe56d0625060834de /src/uapi
parentb82479a69cd6110c9099031e133fda62f8e11222 (diff)
downloadkmi-fdbc5adf83741d7e3af0c3f0ffdb59bdf42493b6.tar.gz
kmi-fdbc5adf83741d7e3af0c3f0ffdb59bdf42493b6.zip
generalize orphants
+ Allow threads to make themselves become orphants
Diffstat (limited to 'src/uapi')
-rw-r--r--src/uapi/dispatch.c1
-rw-r--r--src/uapi/ipc.c19
-rw-r--r--src/uapi/proc.c29
3 files changed, 41 insertions, 8 deletions
diff --git a/src/uapi/dispatch.c b/src/uapi/dispatch.c
index 7cfce4c..c4ad811 100644
--- a/src/uapi/dispatch.c
+++ b/src/uapi/dispatch.c
@@ -81,6 +81,7 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b,
case SYS_POWEROFF: sys_poweroff(t, a, b, c, d, e); break;
case SYS_SLEEP: sys_sleep(t, a, b, c, d, e); break;
case SYS_IRQ_REQ: sys_irq_req(t, a, b, c, d, e); break;
+ case SYS_DETACH: sys_detach(t, a, b, c, d, e); break;
case SYS_EXIT: sys_exit(t, a, b, c, d, e); break;
default:
error("Syscall %zu outside allowed range [0 - %i]\n", syscall,
diff --git a/src/uapi/ipc.c b/src/uapi/ipc.c
index f3896f5..bc49dbb 100644
--- a/src/uapi/ipc.c
+++ b/src/uapi/ipc.c
@@ -83,7 +83,7 @@ static vm_t enter_rpc(struct tcb *t, struct sys_ret a,
{
/* reuse current rpc stack location if we're being kicked */
vm_t rpc_stack = (kind == IPC_KICK &&
- is_rpc(t)) ? t->rpc_stack :rpc_position(t);
+ is_rpc(t)) ? t->rpc_stack : rpc_position(t);
struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1;
ctx->regs = t->regs;
@@ -179,8 +179,8 @@ void notify(struct tcb *t, enum notify_flag flag)
return;
struct tcb *r = get_tcb(t->notify_id);
- if (!r || !r->callback) {
- error("notify callback dead\n");
+ if (!r || r->state || !r->callback) {
+ error("notify callback unavailable\n");
t->notify_flags = 0;
return;
}
@@ -218,31 +218,34 @@ static void leave_rpc(struct tcb *t, struct sys_ret a)
{
vm_t rpc_stack = t->rpc_stack + BASE_PAGE_SIZE;
struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1;
- vm_t top = ctx->rpc_stack;
t->regs = ctx->regs;
/* again, get rid of args as fast as possible */
set_args(t, 6, a);
struct tcb *r = get_tcb(ctx->pid);
- while (!r || r->dead) {
+ while (!r || !is_proc(r) || zombie(r)) {
/* we unwound back to our root process which is apparently dead,
* we're orphaned :( */
- if (ctx->pid == t->rid) {
+ if (rpc_stack_empty(ctx->rpc_stack)) {
orphanize(t);
- return;
+ break;
}
rpc_stack = ctx->rpc_stack + BASE_PAGE_SIZE;
ctx = (struct call_ctx *)(rpc_stack) - 1;
r = get_tcb(ctx->pid);
+ set_args1(t, ERR_NF);
}
+ if (orphan(t) && !is_rpc(t))
+ unorphanize(t);
+
set_return(t, ctx->exec);
/* if we're returning from a failed rpc, this should essentially be a
* no-op */
- mark_rpc_valid(t, top);
+ mark_rpc_valid(t, ctx->rpc_stack);
t->rpc_stack = ctx->rpc_stack;
t->pid = ctx->pid;
t->eid = ctx->eid;
diff --git a/src/uapi/proc.c b/src/uapi/proc.c
index 3ce808f..231cc32 100644
--- a/src/uapi/proc.c
+++ b/src/uapi/proc.c
@@ -235,6 +235,35 @@ SYSCALL_DEFINE1(exit)(struct tcb *t, sys_arg_t tid)
}
/**
+ * Syscall handler for orphanizing a thread.
+ *
+ * @param t Thread that wants to make itself an orphant.
+ * @return \ref OK on success,
+ * \ref ERR_PERM if current process missing \ref CAP_PROC,
+ * \ref ERR_INVAL if already an orphant.
+ */
+SYSCALL_DEFINE0(detach)(struct tcb *t)
+{
+ struct tcb *c = get_cproc(t);
+ if (!(has_cap(c->caps, CAP_PROC)))
+ return_args1(t, ERR_PERM);
+
+ if (orphan(t))
+ return_args1(t, ERR_INVAL);
+
+ struct tcb *r = get_tcb(t->rid);
+ if (r)
+ unreference_proc(r);
+
+ orphanize(t);
+
+ if (!is_rpc(t))
+ unorphanize(t);
+
+ return_args1(t, OK);
+}
+
+/**
* Swap syscall handler.
*
* \todo Implement.