aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-10-21 17:43:31 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2022-10-21 17:43:31 +0300
commitec989bbe7d9bb7a844eeddeceaeb7bb7e4d5dab6 (patch)
tree51221980ad2d4c8701e1a6e762a47495dec289de
parenta06dbb8a63d825ebb1ad65372ce1ce1f572891bc (diff)
downloadkmi-ec989bbe7d9bb7a844eeddeceaeb7bb7e4d5dab6.tar.gz
kmi-ec989bbe7d9bb7a844eeddeceaeb7bb7e4d5dab6.zip
initial implementation of swap
+ Slightly unsure if it should be a syscall, or if assign would be enough. Also, which thread should run in a fork/spawn? For now, old thread, though this might increase latency. Or add swap flag to these calls?
-rw-r--r--arch/riscv64/kernel/proc.c28
-rw-r--r--common/proc.c2
-rw-r--r--common/tcb.c4
-rw-r--r--common/uapi/proc.c15
-rw-r--r--include/apos/utils.h11
-rw-r--r--include/arch/proc.h28
6 files changed, 63 insertions, 25 deletions
diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c
index f85f597..10f8bfa 100644
--- a/arch/riscv64/kernel/proc.c
+++ b/arch/riscv64/kernel/proc.c
@@ -8,10 +8,13 @@
#include <apos/tcb.h>
#include <apos/elf.h>
+
+#include <arch/proc.h>
+
#include "regs.h"
#include "csr.h"
-stat_t run_init(struct tcb *t, void *fdt)
+void run_init(struct tcb *t, void *fdt)
{
/** \todo actually map fdt into the target address space */
csr_write(CSR_SSCRATCH, t);
@@ -20,18 +23,27 @@ stat_t run_init(struct tcb *t, void *fdt)
__asm__ volatile ("mv a0, %0\n" : : "r" (fdt) : );
__asm__ volatile ("sret\n" ::: "memory");
/* we should never reach this */
- return ERR_ADDR;
+ unreachable();
}
-stat_t set_ipc(struct tcb *t, id_t pid, id_t tid)
+void set_args(struct tcb *t, struct sys_ret a)
{
struct riscv_regs *r = (struct riscv_regs *)(--t);
- r->a2 = (long)pid;
- r->a3 = (long)tid;
- return OK;
+ r->a0 = a.s;
+ r->a1 = a.ar0;
+ r->a2 = a.ar1;
+ r->a3 = a.ar2;
+ r->a4 = a.ar3;
+ r->a5 = a.ar4;
}
-stat_t set_thread(struct tcb *t)
+struct sys_ret get_args(struct tcb *t)
+{
+ struct riscv_regs *r = (struct riscv_regs *)(--t);
+ return (struct sys_ret){r->a0, r->a1, r->a2, r->a3, r->a4, r->a5};
+}
+
+void set_thread(struct tcb *t)
{
/* get location of registers in memory */
/** \todo check alignment, should be fine but just to be sure */
@@ -40,6 +52,4 @@ stat_t set_thread(struct tcb *t)
/* insert important values into register slots */
r->sp = (long)t->thread_stack_top;
r->tp = (long)t->thread_storage;
-
- return OK;
}
diff --git a/common/proc.c b/common/proc.c
index 6a3bedf..946078b 100644
--- a/common/proc.c
+++ b/common/proc.c
@@ -37,9 +37,7 @@ stat_t init_proc(void *fdt)
return ERR_OOMEM;
/* set current tcb */
- cpu_assign(t);
use_tcb(t);
- use_vmem(t->proc.vmem);
/* allocate stacks after ELF file to make sure nothing of importance
* clashes */
diff --git a/common/tcb.c b/common/tcb.c
index f618cd6..42e634d 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -305,9 +305,13 @@ struct tcb *cur_proc()
void use_tcb(struct tcb *t)
{
+ cpu_assign(t);
+
id_t cpu = cpu_id();
t->cpu_id = cpu;
cpu_tcb[cpu] = t;
+
+ use_vmem(t->proc.vmem);
}
struct tcb *get_tcb(id_t tid)
diff --git a/common/uapi/proc.c b/common/uapi/proc.c
index a668246..a9a3dce 100644
--- a/common/uapi/proc.c
+++ b/common/uapi/proc.c
@@ -12,6 +12,8 @@
#include <apos/bits.h>
#include <apos/mem_regions.h>
+#include <arch/proc.h>
+
/**
* Create syscall handler.
*
@@ -122,10 +124,15 @@ SYSCALL_DEFINE1(kill)(sys_arg_t tid)
* @return \ref OK and 0.
*/
SYSCALL_DEFINE1(swap)(sys_arg_t tid){
- /** \todo switch to process */
- /** \todo should switch return the registers of the new thread that would
- * be used for message passing? */
- return (struct sys_ret){ OK, 0, 0, 0, 0, 0 };
+ struct tcb *t = get_tcb(tid);
+ if (!t)
+ /** @todo add error sys_ret macro? */
+ return (struct sys_ret){ERR_INVAL, 0, 0, 0, 0, 0};
+
+ /* switch over to new thread */
+ use_tcb(t);
+
+ return get_args(t);
}
/**
diff --git a/include/apos/utils.h b/include/apos/utils.h
index 29969c4..6eeb54f 100644
--- a/include/apos/utils.h
+++ b/include/apos/utils.h
@@ -187,6 +187,17 @@
#endif
/**
+ * Signal to the compiler that some region is unreachable.
+ * Mainly used for debugging with instrumentation, though it could provide some
+ * micro-optimisations.
+*/
+#if __has_builtin(__builtin_unreachable)
+#define unreachable() __builtin_unreachable()
+#else
+#define unreachable()
+#endif
+
+/**
* Get container of some member.
*
* @param ptr Pointer to member in some structure.
diff --git a/include/arch/proc.h b/include/arch/proc.h
index d5367f6..5ea0f0f 100644
--- a/include/arch/proc.h
+++ b/include/arch/proc.h
@@ -15,18 +15,28 @@
#include "../../arch/riscv32/include/proc.h"
#endif
+#include <apos/uapi.h>
+
/**
- * Attach IPC data to load into argument registers when returning to userspace.
+ * Attach argument data to thread.
*
* @param t Thread that will run after return.
- * @param pid Process ID.
- * @param tid Thread ID.
- * @return \ref OK.
+ * @param a Arguments to attach.
+ */
+void set_args(struct tcb *t, struct sys_ret a);
+
+/**
+ * Get argument data attached to thread.
+ * To some extent a hack, used by swap.
+ *
+ * @todo is swap necessary? Would assign be enough?
+ *
+ * @param t Thread to read data from.
+ * @return Args associated with thread.
*/
-stat_t set_ipc(struct tcb *t, id_t pid, id_t tid);
+struct sys_ret get_args(struct tcb *t);
/** \todo Should these be in arch/tcb.h or something? */
-/** \todo Should these be void? */
/**
* Attach thread stack and thread local storage when returning to userspace.
@@ -35,17 +45,15 @@ stat_t set_ipc(struct tcb *t, id_t pid, id_t tid);
* actualizes the information.
*
* @param t Thread that will run after return.
- * @return \ref OK.
*/
-stat_t set_thread(struct tcb *t);
+void set_thread(struct tcb *t);
/**
* Run \c init program.
*
* @param t Thread that \c init is attached to.
* @param fdt Pointer to FDT that is passed to \c init.
- * @return \ref ERR_ADDR, as it shouldn't return-
*/
-stat_t run_init(struct tcb *t, void *fdt);
+__noreturn void run_init(struct tcb *t, void *fdt);
#endif /* APOS_ARCH_PROC_H */