diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-11-09 16:27:23 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-11-09 17:27:11 +0200 |
| commit | a3e45d5dcaf1bf3a9e684b5fcc301413ec994a9b (patch) | |
| tree | ae319c8f389e7ca39bbdd4b114655f8604563305 /common | |
| parent | 2b5533aefef026fe7bada314ebdb2651b809979a (diff) | |
| download | kmi-a3e45d5dcaf1bf3a9e684b5fcc301413ec994a9b.tar.gz kmi-a3e45d5dcaf1bf3a9e684b5fcc301413ec994a9b.zip | |
add basic IPI structure
Diffstat (limited to 'common')
| -rw-r--r-- | common/dispatch.c | 12 | ||||
| -rw-r--r-- | common/ipi.c | 32 | ||||
| -rw-r--r-- | common/tcb.c | 16 | ||||
| -rw-r--r-- | common/uapi/dispatch.c | 9 | ||||
| -rw-r--r-- | common/uapi/ipc.c | 42 |
5 files changed, 77 insertions, 34 deletions
diff --git a/common/dispatch.c b/common/dispatch.c new file mode 100644 index 0000000..1325d62 --- /dev/null +++ b/common/dispatch.c @@ -0,0 +1,12 @@ +#include <apos/uapi.h> +#include <apos/ipi.h> + +struct sys_ret dispatch(sys_arg_t a, sys_arg_t b, sys_arg_t c, + sys_arg_t d, sys_arg_t e, sys_arg_t f) +{ + struct tcb *t = cur_tcb(); + if (clear_ipi(t)) + return handle_ipi(t); + + return handle_syscall(t, a, b, c, d, e, f); +} diff --git a/common/ipi.c b/common/ipi.c new file mode 100644 index 0000000..32f1432 --- /dev/null +++ b/common/ipi.c @@ -0,0 +1,32 @@ +#include <apos/ipi.h> +#include <arch/cpu.h> + +#include <arch/proc.h> + +/** + * @file ipi.c + * + * IPI function implementations. + */ + +bool clear_ipi(struct tcb *t) +{ + bool r = t->ipi; + t->ipi = false; + return r; +} + +void send_ipi(struct tcb *t) +{ + t->ipi = true; + cpu_send_ipi(t->cpu_id); +} + +struct sys_ret handle_ipi(struct tcb *t) +{ + adjust_ipi(t); + + /** @todo use rpc stack */ + set_return(t, t->callback); + return get_args(t); +} diff --git a/common/tcb.c b/common/tcb.c index 9000941..417ca45 100644 --- a/common/tcb.c +++ b/common/tcb.c @@ -36,7 +36,7 @@ static struct tcb **tcbs; * \todo If we ever support systems with massive amounts of cpus, this should probably * be allocated at runtime. */ -static struct tcb *cpu_tcb[MAX_CPUS] = { 0 }; +static struct tcb *__cpu_tcb[MAX_CPUS] = { 0 }; void init_tcbs() { @@ -294,7 +294,12 @@ DEFINE_DETACH(detach_proc, proc); /* weak to allow optimisation on risc-v, but provide fallback for future */ __weak struct tcb *cur_tcb() { - return cpu_tcb[cpu_id()]; + return cpu_tcb(cpu_id()); +} + +struct tcb *cpu_tcb(id_t cpu_id) +{ + return __cpu_tcb[cpu_id]; } struct tcb *cur_proc() @@ -313,7 +318,7 @@ void use_tcb(struct tcb *t) { cpu_assign(t); - cpu_tcb[t->cpu_id] = t; + __cpu_tcb[t->cpu_id] = t; use_vmem(t->proc.vmem); } @@ -355,3 +360,8 @@ void set_return(struct tcb *t, vm_t v) { t->exec = v; } + +bool running(struct tcb *t) +{ + return cpu_tcb(t->cpu_id) == t; +} diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c index 27cc001..2cf19fb 100644 --- a/common/uapi/dispatch.c +++ b/common/uapi/dispatch.c @@ -10,6 +10,8 @@ #include <apos/debug.h> #include <apos/uapi.h> +#include <arch/proc.h> + /** Syscall number to syscall handler conversion. */ static const sys_t syscall_table[] = { /* noop */ @@ -79,10 +81,11 @@ SYSCALL_DEFINE1(putch)(sys_arg_t a){ return SYS_RET1(OK); } -struct sys_ret syscall_dispatch(sys_arg_t syscall, sys_arg_t a, sys_arg_t b, - sys_arg_t c, sys_arg_t d, sys_arg_t e) +struct sys_ret handle_syscall(struct tcb *t, + sys_arg_t syscall, sys_arg_t a, sys_arg_t b, + sys_arg_t c, sys_arg_t d, sys_arg_t e) { - struct tcb *t = cur_tcb(); + adjust_syscall(t); size_t sc = syscall; if (sc >= ARRAY_SIZE(syscall_table)) { diff --git a/common/uapi/ipc.c b/common/uapi/ipc.c index 34f707a..cb53ee3 100644 --- a/common/uapi/ipc.c +++ b/common/uapi/ipc.c @@ -8,6 +8,7 @@ #include <apos/uapi.h> #include <apos/tcb.h> +#include <apos/ipi.h> /** * IPC server notification syscall handler. @@ -114,36 +115,21 @@ SYSCALL_DEFINE4(ipc_resp)(sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, * \todo Implement. * * @param tid Thread ID to notify. - * @param swap Whether to swap immediately if possible. * @return \ref OK and 0. */ -SYSCALL_DEFINE2(ipc_notify)(sys_arg_t tid, sys_arg_t swap){ - /** \todo masquerade as kernel call, set from to 0 and set us as - * notify type, no arguments as that would require too much state - * handling for my liking. Instead, a server and a client have to agree - * on some rpc API, and ipc_notify is just used to asynchronously inform - * the client that it should check the status of its async operations. - * Arguably slower than directly telling the client which operation was - * finished, but this would require the kernel to keep track of a notify - * stack. While not impossible, probably too complex. */ +SYSCALL_DEFINE1(ipc_notify)(sys_arg_t tid){ + struct tcb *t = get_tcb(tid); + if (t->notify_state == NOTIFY_QUEUED) + return SYS_RET1(OK); + + if (t->notify_state == NOTIFY_RUNNING) { + t->notify_state = NOTIFY_QUEUED; + return SYS_RET1(OK); + } + + t->notify_state = NOTIFY_QUEUED; + if (running(t)) + send_ipi(t); - /* Something like - * - * struct tcb *t = get_tcb(tid); - * if (t->notify_state == NOTIFY_QUEUED) - * return; - * - * if (t->notify_state == NOTIFY_RUNNING) { - * t->notify = NOTIFY_QUEUED; - * return; - * } - * - * t->notify_state = NOTIFY_QUEUED; - * if (swap) - * do_swap(); // clears t->notify when swapped to - * // if already running in base state, interrupt, - * otherwise wait for return from rpc. If not running, - * just queue the interrupt. - */ return SYS_RET1(OK); } |
