aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xarch/riscv64/conf/initbin2560 -> 2664 bytes
-rw-r--r--arch/riscv64/conf/init.c11
-rw-r--r--arch/riscv64/conf/initrdbin3072 -> 3072 bytes
-rw-r--r--arch/riscv64/kernel/proc.c17
-rw-r--r--common/tcb.c19
-rw-r--r--common/uapi/proc.c9
-rw-r--r--common/vmem.c28
-rw-r--r--include/apos/vmem.h10
-rw-r--r--include/arch/proc.h8
9 files changed, 80 insertions, 22 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init
index 47e733f..11d838c 100755
--- a/arch/riscv64/conf/init
+++ b/arch/riscv64/conf/init
Binary files differ
diff --git a/arch/riscv64/conf/init.c b/arch/riscv64/conf/init.c
index 1886760..45274d9 100644
--- a/arch/riscv64/conf/init.c
+++ b/arch/riscv64/conf/init.c
@@ -133,10 +133,15 @@ void _start()
if (pid != 0) {
print_value("Child pid: ", pid);
puts("Swapping to child...\n");
- sys_swap(pid);
- puts("We shouldn't be here?\n");
- while(1);
+ while(1) sys_swap(pid);
}
puts("Hello from child!\n");
+
+ puts("Doing 1M swaps...\n");
+ start = sys_ticks();
+ for (long i = 0; i < 1000000; ++i)
+ sys_swap(1);
+ uint64_t ticks = sys_ticks() - start;
+ print_value("1M swaps took ", ticks / second);
}
diff --git a/arch/riscv64/conf/initrd b/arch/riscv64/conf/initrd
index 24f9fb4..5c0c9bb 100644
--- a/arch/riscv64/conf/initrd
+++ b/arch/riscv64/conf/initrd
Binary files differ
diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c
index d2b8dfb..2ccc5bc 100644
--- a/arch/riscv64/kernel/proc.c
+++ b/arch/riscv64/kernel/proc.c
@@ -30,7 +30,7 @@ void run_init(struct tcb *t, void *fdt)
void set_args(struct tcb *t, struct sys_ret a)
{
- struct riscv_regs *r = (struct riscv_regs *)(--t);
+ struct riscv_regs *r = (struct riscv_regs *)(t) - 1;
r->a0 = a.s;
r->a1 = a.ar0;
r->a2 = a.ar1;
@@ -41,7 +41,7 @@ void set_args(struct tcb *t, struct sys_ret a)
struct sys_ret get_args(struct tcb *t)
{
- struct riscv_regs *r = (struct riscv_regs *)(--t);
+ struct riscv_regs *r = (struct riscv_regs *)(t) - 1;
return SYS_RET6(r->a0, r->a1, r->a2, r->a3, r->a4, r->a5);
}
@@ -49,7 +49,7 @@ void set_thread(struct tcb *t)
{
/* get location of registers in memory */
/** \todo check alignment, should be fine but just to be sure */
- struct riscv_regs *r = (struct riscv_regs *)(--t);
+ struct riscv_regs *r = (struct riscv_regs *)(t) - 1;
/* insert important values into register slots */
r->sp = (long)t->thread_stack_top;
@@ -58,16 +58,23 @@ void set_thread(struct tcb *t)
void save_regs(struct tcb *t, void *p)
{
- struct riscv_regs *r = (struct riscv_regs *)(t++);
+ struct riscv_regs *r = (struct riscv_regs *)(t) - 1;
memcpy(p, r, sizeof(*r));
}
void load_regs(void *p, struct tcb *t)
{
- struct riscv_regs *r = (struct riscv_regs *)(t++);
+ struct riscv_regs *r = (struct riscv_regs *)(t) - 1;
memcpy(r, p, sizeof(*r));
}
+void clone_regs(struct tcb *d, struct tcb *s)
+{
+ struct riscv_regs *rd = (struct riscv_regs *)(d) - 1;
+ struct riscv_regs *rs = (struct riscv_regs *)(s) - 1;
+ memcpy(rd, rs, sizeof(*rs));
+}
+
void adjust_ipi(struct tcb *t)
{
UNUSED(t);
diff --git a/common/tcb.c b/common/tcb.c
index 5f0e97b..0a676af 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -19,6 +19,7 @@
#include <arch/cpu.h>
#include <arch/vmem.h>
+#include <arch/proc.h>
/* arguably exessively many globals... */
/** Thread ID to start looking from when allocating new ID. */
@@ -63,7 +64,7 @@ static id_t __alloc_tid(struct tcb *t)
{
/** \todo this would need some locking or something... */
for (size_t i = start_tid; i < num_tids; ++i) {
- if (tcbs[i])
+ if (tcbs[i] || i == 0)
continue;
tcbs[i] = t;
@@ -158,6 +159,7 @@ struct tcb *create_thread(struct tcb *p)
init_uvmem(t, UVMEM_START, UVMEM_END);
t->proc.vmem = create_vmem();
t->pid = t->tid;
+ t->rid = t->tid;
p = t;
}
@@ -172,13 +174,20 @@ struct tcb *create_thread(struct tcb *p)
/**
* Copy process.
*
- * @param n New process.
* @param p Parent process.
+ * @param n New process.
* @return \ref OK.
*/
-static stat_t __copy_proc(struct tcb *n, struct tcb *p)
+static stat_t __copy_proc(struct tcb *p, struct tcb *n)
{
- /* execution continuation? */
+ /** @todo setup rpc stack stuff */
+ /** @todo I think keeping track of userspace stack stuff is unnecessary,
+ * unless we want unlimited stack size but that sounds dumb. Anycase, we
+ * need to duplicate stack info, whatever we do. */
+ /** @todo should there be in-kernel child tracking? */
+ n->exec = p->exec;
+ clone_regs(n, p);
+ copy_caps(n->caps, p->caps);
return clone_mem_regions(n, p);
}
@@ -191,7 +200,7 @@ struct tcb *create_proc(struct tcb *p)
if (!n)
return 0;
- if (likely(p))
+ if (p)
__copy_proc(p, n); /* we have a parent thread */
return n;
diff --git a/common/uapi/proc.c b/common/uapi/proc.c
index 5dbd90c..969dcd6 100644
--- a/common/uapi/proc.c
+++ b/common/uapi/proc.c
@@ -62,8 +62,9 @@ SYSCALL_DEFINE0(fork)(){
if (!t)
return SYS_RET1(ERR_OOMEM);
- /* prepare args for when we eventually swap to the new proc */
- set_args(t, SYS_RET2(OK, 0));
+ /* prepare args for when we eventually swap to the new proc, giving
+ * parent ID as third return value */
+ set_args(t, SYS_RET3(OK, 0, c->pid));
return SYS_RET2(OK, t->pid);
}
@@ -166,5 +167,9 @@ SYSCALL_DEFINE1(swap)(sys_arg_t tid){
/* switch over to new thread */
use_tcb(t);
+ /* set return value for current thread */
+ set_args(c, SYS_RET1(OK));
+
+ /* get register state for new thread */
return get_args(t);
}
diff --git a/common/vmem.c b/common/vmem.c
index 42b4adf..458624c 100644
--- a/common/vmem.c
+++ b/common/vmem.c
@@ -19,15 +19,29 @@ stat_t init_uvmem(struct tcb *t, vm_t base, vm_t top)
return init_region(&t->sp_r, base, top);
}
-static stat_t __clone_mapped_region(struct tcb *d, struct tcb *s, struct mem_region *m)
+/**
+ * Clone process memory region.
+ *
+ * @param d Destination tcb.
+ * @param s Source tcb.
+ * @param m Memory region to clone.
+ * @return \ref ERR_MISC if clone failed, otherwise \ref OK.
+ *
+ * @todo check shared memory regions.
+ */
+static stat_t __clone_mapped_region(struct tcb *d, struct tcb *s,
+ struct mem_region *m)
{
- size_t size = 0;
- vm_t va = alloc_fixed_region(&d->sp_r, m->start, m->end - m->start,
- &size, m->flags);
+ vm_t start = m->start * order_size(BASE_PAGE);
+ vm_t end = m->end * order_size(BASE_PAGE);
+
+ size_t size = end - start, actual_size = 0;
+ vm_t va = alloc_fixed_region(&d->sp_r, start, size,
+ &actual_size, m->flags);
- catastrophic_assert(va == m->start);
+ catastrophic_assert(va == start);
- if (copy_allocd_region(d->proc.vmem, va, size, m->flags, s))
+ if (!copy_allocd_region(d->proc.vmem, va, size, m->flags, s->proc.vmem))
return ERR_MISC;
return OK;
@@ -220,7 +234,7 @@ stat_t alloc_shared_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr,
}
stat_t copy_allocd_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr,
- vmflags_t flags, enum mm_order order, void *data)
+ vmflags_t flags, enum mm_order order, void *data)
{
struct vmem *s = (struct vmem *)data;
diff --git a/include/apos/vmem.h b/include/apos/vmem.h
index 862af44..1e481fa 100644
--- a/include/apos/vmem.h
+++ b/include/apos/vmem.h
@@ -114,6 +114,16 @@ stat_t init_uvmem(struct tcb *r, vm_t base, vm_t top);
*/
stat_t destroy_uvmem(struct tcb *r);
+/**
+ * Clone process memory.
+ *
+ * @param d Destination tcb.
+ * @param s Source tcb.
+ * @return OK.
+ *
+ * @todo Come up with better name. clone_uvmem() is taken, but should it be
+ * renamed to clone_mapping() or something?
+ */
stat_t clone_mem_regions(struct tcb *d, struct tcb *s);
/**
diff --git a/include/arch/proc.h b/include/arch/proc.h
index a64f978..e2b99ea 100644
--- a/include/arch/proc.h
+++ b/include/arch/proc.h
@@ -67,6 +67,14 @@ void save_regs(struct tcb *t, void *p);
void load_regs(void *p, struct tcb *t);
/**
+ * Copy registers from one thread to another. Used by \ref fork(), for example.
+ *
+ * @param d Destination.
+ * @param s Source.
+ */
+void clone_regs(struct tcb *d, struct tcb *s);
+
+/**
* Do modifications to \ref tcb state if necessary for ipis to work.
*
* @param t Thread to do modifications to.