diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-11-11 19:46:22 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-11-11 19:46:22 +0200 |
| commit | 1d37792fb7a47135f0e7b7fc245e83bb1d8fc496 (patch) | |
| tree | 09ec92012bb9d74d5d26bc7a4a7647c36c9acb3e | |
| parent | 9edd65c48ee75751327c6ee6d42a7009e726d667 (diff) | |
| download | kmi-1d37792fb7a47135f0e7b7fc245e83bb1d8fc496.tar.gz kmi-1d37792fb7a47135f0e7b7fc245e83bb1d8fc496.zip | |
less buggy fork
+ Not strictly done yet, but we can swap between two processes :D
| -rwxr-xr-x | arch/riscv64/conf/init | bin | 2560 -> 2664 bytes | |||
| -rw-r--r-- | arch/riscv64/conf/init.c | 11 | ||||
| -rw-r--r-- | arch/riscv64/conf/initrd | bin | 3072 -> 3072 bytes | |||
| -rw-r--r-- | arch/riscv64/kernel/proc.c | 17 | ||||
| -rw-r--r-- | common/tcb.c | 19 | ||||
| -rw-r--r-- | common/uapi/proc.c | 9 | ||||
| -rw-r--r-- | common/vmem.c | 28 | ||||
| -rw-r--r-- | include/apos/vmem.h | 10 | ||||
| -rw-r--r-- | include/arch/proc.h | 8 |
9 files changed, 80 insertions, 22 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init Binary files differindex 47e733f..11d838c 100755 --- a/arch/riscv64/conf/init +++ b/arch/riscv64/conf/init 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 Binary files differindex 24f9fb4..5c0c9bb 100644 --- a/arch/riscv64/conf/initrd +++ b/arch/riscv64/conf/initrd 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. |
