diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-07-27 18:39:54 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-07-27 18:39:54 +0300 |
| commit | a26fb216729ba7a7d0fbfc97c2082c9db512aa36 (patch) | |
| tree | deb10d29615187bb0788b7b5ae82004909add3e5 /common/uapi | |
| parent | 8701c9b47319202e845fb12b3e7f7bc829b4c144 (diff) | |
| download | kmi-a26fb216729ba7a7d0fbfc97c2082c9db512aa36.tar.gz kmi-a26fb216729ba7a7d0fbfc97c2082c9db512aa36.zip | |
add ipc_kick
+ Tests will have to come later
Diffstat (limited to 'common/uapi')
| -rw-r--r-- | common/uapi/dispatch.c | 1 | ||||
| -rw-r--r-- | common/uapi/ipc.c | 60 |
2 files changed, 52 insertions, 9 deletions
diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c index 8ffbf54..d071db3 100644 --- a/common/uapi/dispatch.c +++ b/common/uapi/dispatch.c @@ -61,6 +61,7 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b, case SYS_IPC_SERVER: sys_ipc_server(t, a, b, c, d, e); break; case SYS_IPC_REQ: sys_ipc_req(t, a, b, c, d, e); break; case SYS_IPC_FWD: sys_ipc_fwd(t, a, b, c, d, e); break; + case SYS_IPC_KICK: sys_ipc_kick(t, a, b, c, d, e); break; case SYS_IPC_RESP: sys_ipc_resp(t, a, b, c, d, e); break; case SYS_IPC_NOTIFY: sys_ipc_notify(t, a, b, c, d, e); break; case SYS_CREATE: sys_create(t, a, b, c, d, e); break; diff --git a/common/uapi/ipc.c b/common/uapi/ipc.c index 74b5732..c2548e9 100644 --- a/common/uapi/ipc.c +++ b/common/uapi/ipc.c @@ -64,6 +64,9 @@ struct call_ctx { /** Current process ID. */ id_t pid; + + /** Whether this context should be skipped when responding. */ + bool kick; }; /** @@ -77,6 +80,11 @@ struct stack_diff { vm_t end; }; +/** Enumerator for IPC kind. Used by do_ipc(). */ +enum ipc_kind { + IPC_REQ, IPC_FWD, IPC_KICK +}; + /** * Now that we know we're doing an rpc, clone virtual memories and do * the slow stuff. @@ -104,9 +112,11 @@ static void finalize_rpc(struct tcb *t, struct tcb *r, struct stack_diff sd) * * @param t Thread to migrate. * @param a RPC arguments. + * @param kind Kind of IPC we're doing. Essentially toggles kick boolean. * @return RPC stack difference that should be passed to finalize_rpc(). */ -static struct stack_diff enter_rpc(struct tcb *t, struct sys_ret a) +static struct stack_diff enter_rpc(struct tcb *t, struct sys_ret a, + enum ipc_kind kind) { vm_t rpc_stack = t->rpc_stack; if (is_rpc(t)) @@ -131,6 +141,9 @@ static struct stack_diff enter_rpc(struct tcb *t, struct sys_ret a) ctx->eid = t->eid; ctx->rpc_stack = rpc_stack; + /* only rpcs can be kicked forward */ + ctx->kick = kind == IPC_KICK && is_rpc(t); + /** @todo if we run out of rpc_stack space we should just stop, likely * return a status? except it shouldn't happen after we've run * enough_rpc_stack(). */ @@ -162,6 +175,14 @@ 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; + + /* find first instance of not kicked context */ + while (ctx->kick) { + rpc_stack = ctx->rpc_stack + BASE_PAGE_SIZE; + ctx = (struct call_ctx *)(rpc_stack) - 1; + } + t->regs = ctx->regs; /* again, get rid of args as fast as possible */ set_args(t, a); @@ -169,7 +190,7 @@ static void leave_rpc(struct tcb *t, struct sys_ret a) set_return(t, ctx->exec); /* if we're returning from a failed rpc, this should essentially be a * no-op */ - mark_rpc_accessible(t, t->rpc_stack, ctx->rpc_stack); + mark_rpc_accessible(t, t->rpc_stack, top); t->rpc_stack = ctx->rpc_stack; t->pid = ctx->pid; t->eid = ctx->eid; @@ -221,12 +242,15 @@ SYSCALL_DEFINE1(ipc_server)(struct tcb *t, sys_arg_t callback) * @param d1 IPC argument 1. * @param d2 IPC argument 2. * @param d3 IPC argument 3. - * @param fwd Whether to forward. + * @param kind Which kind of IPC to perform. * * Returns \ref ERR_OOMEM if there isn't enough IPC stack left, \ref ERR_INVAL * if the the target process doesn't exist, \ref ERR_NOINIT if the target * process hasn't defined a callback. Otherwise \ref OK and whatever the target * process sends back. + * + * @todo should all static functions have double underscores? I seem to be + * inconsistent. */ static void do_ipc(struct tcb *t, sys_arg_t pid, @@ -234,13 +258,13 @@ static void do_ipc(struct tcb *t, sys_arg_t d1, sys_arg_t d2, sys_arg_t d3, - bool fwd) + enum ipc_kind kind) { if (unlikely(!enough_rpc_stack(t))) return_args(t, SYS_RET1(ERR_OOMEM)); struct stack_diff sd = - enter_rpc(t, SYS_RET6(OK, t->eid, d0, d1, d2, d3)); + enter_rpc(t, SYS_RET6(OK, t->eid, d0, d1, d2, d3), kind); struct tcb *r = get_tcb(pid); if (unlikely(!r)) { @@ -255,7 +279,7 @@ static void do_ipc(struct tcb *t, return; } - if (!fwd) + if (kind != IPC_REQ) t->eid = t->pid; finalize_rpc(t, r, sd); @@ -275,7 +299,7 @@ static void do_ipc(struct tcb *t, SYSCALL_DEFINE5(ipc_req)(struct tcb *t, sys_arg_t pid, sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, sys_arg_t d3) { - do_ipc(t, pid, d0, d1, d2, d3, false); + do_ipc(t, pid, d0, d1, d2, d3, IPC_REQ); } /** @@ -287,12 +311,30 @@ SYSCALL_DEFINE5(ipc_req)(struct tcb *t, sys_arg_t pid, * @param d1 IPC argument 1. * @param d2 IPC argument 2. * @param d3 IPC argument 3. - * @return + * @return When succesful: OK, thread id of the caller and the arguments as-is. */ SYSCALL_DEFINE5(ipc_fwd)(struct tcb *t, sys_arg_t pid, sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, sys_arg_t d3) { - do_ipc(t, pid, d0, d1, d2, d3, true); + do_ipc(t, pid, d0, d1, d2, d3, IPC_FWD); +} + +/** + * IPC kicking syscall handler. + * + * @param t Current tcb. + * @param pid Process to request RPC to. + * @param d0 IPC argument 0. + * @param d1 IPC argument 1. + * @param d2 IPC argument 2. + * @param d3 IPC argument 3. + * @return When succesful: OK, thread id of the caller and the arguments as-is. + */ +SYSCALL_DEFINE5(ipc_kick)(struct tcb *t, sys_arg_t pid, + sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, + sys_arg_t d3) +{ + do_ipc(t, pid, d0, d1, d2, d3, IPC_KICK); } /** |
