diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/dmem.c | 11 | ||||
| -rw-r--r-- | common/tcb.c | 97 | ||||
| -rw-r--r-- | common/uapi/ipc.c | 12 | ||||
| -rw-r--r-- | common/vmem.c | 43 |
4 files changed, 46 insertions, 117 deletions
diff --git a/common/dmem.c b/common/dmem.c index b903cbe..bbabe09 100644 --- a/common/dmem.c +++ b/common/dmem.c @@ -106,14 +106,15 @@ vm_t alloc_devmem(struct tcb *t, pm_t dev_start, size_t bytes, vmflags_t flags) region = alloc_region(&post_ram, bytes, 0, flags); if (!region) - return 0; + return NULL; stat_t status = OK; const vm_t w = map_fill_region(t->proc.vmem, &dev_alloc_wrapper, dev_start, region, bytes, flags, &status); - if (is_rpc(t) && status == INFO_SEFF) - clone_rpc_maps(t); + + if (status) + return NULL; return w; } @@ -142,8 +143,6 @@ stat_t free_devmem(struct tcb *t, vm_t dev_start) stat_t status = OK; map_fill_region(t->proc.vmem, &dev_free_wrapper, dev_paddr, dev_start, region_size, 0, &status); - if (is_rpc(t) && status == INFO_SEFF) - clone_rpc_maps(t); if (dev_paddr < __pre_top) free_region(&pre_ram, dev_paddr); @@ -151,5 +150,5 @@ stat_t free_devmem(struct tcb *t, vm_t dev_start) if (dev_paddr > __post_base) free_region(&post_ram, dev_paddr); - return OK; + return status; } diff --git a/common/tcb.c b/common/tcb.c index e69f2f0..4b57c06 100644 --- a/common/tcb.c +++ b/common/tcb.c @@ -125,6 +125,7 @@ struct tcb *create_thread(struct tcb *p) id_t tid = __alloc_tid(t); tcbs[tid] = t; t->tid = tid; + t->dead = false; if (likely(p)) { t->pid = p->pid; @@ -144,6 +145,7 @@ struct tcb *create_thread(struct tcb *p) t->rid = p->rid; t->rpc.vmem = create_vmem(); setup_rpc_stack(t); + reference_proc(p); t->regs = (vm_t)t; @@ -215,10 +217,12 @@ stat_t destroy_thread(struct tcb *t) hard_assert(!is_proc(t), ERR_INVAL); /* remove thread id from list */ + /** @todo what about if thread is in rpc? should it rather just be + * marked dead? */ tcbs[t->tid] = 0; - /* remove thread from process list */ - detach_proc(get_rproc(t), t); + /* remove reference to root process */ + unreference_proc(get_rproc(t)); return __destroy_thread_data(t); } @@ -228,67 +232,28 @@ stat_t destroy_proc(struct tcb *p) hard_assert(tcbs, ERR_NOINIT); hard_assert(is_proc(p), ERR_INVAL); - for (struct tcb *iter = p; (iter = iter->proc.next);) - destroy_thread(iter); + p->dead = true; + /* unreference ourselves */ + unreference_proc(p); catastrophic_assert(destroy_uvmem(p)); return __destroy_thread_data(p); } -stat_t attach_rpc(struct tcb *r, struct tcb *t) +void reference_proc(struct tcb *p) { - hard_assert(r != t, ERR_INVAL); - struct tcb *next = r->server.next; - t->rpc.next = next; - - if (next) { next->rpc.prev = t; } - - t->rpc.prev = r; - r->server.next = t; - return OK; -} - -stat_t attach_proc(struct tcb *r, struct tcb *t) -{ - hard_assert(r != t, ERR_INVAL); - struct tcb *next = r->proc.next; - t->proc.next = next; - - if (next) { next->proc.prev = t; } - - t->proc.prev = r; - r->proc.next = t; - return OK; -} - -stat_t detach_rpc(struct tcb *r, struct tcb *t) -{ - /* rpc handling is slightly more complex since we have separate members - * for server and rpc contexts, where server is the server that - * currently hosts some number of rpc guests. */ - hard_assert(r != t, ERR_INVAL); - struct tcb *prev = t->rpc.prev; - struct tcb *next = t->rpc.next; - - if (prev == r) { r->server.next = next; } - else if (prev) { prev->rpc.next = next; } - - if (next) { next->rpc.prev = prev; } - - return OK; + hard_assert(is_proc(p), RETURN_VOID); + p->refcount++; } -stat_t detach_proc(struct tcb *r, struct tcb *t) +void unreference_proc(struct tcb *p) { - MAYBE_UNUSED(r); - hard_assert(r != t, ERR_INVAL); - struct tcb *prev = t->proc.prev; - struct tcb *next = t->proc.next; - - if (prev) { prev->proc.next = next; } - if (next) { next->proc.prev = prev; } - - return OK; + hard_assert(is_proc(p), RETURN_VOID); + p->refcount--; + if (p->dead && p->refcount == 0) { + dbg("thread %d is completely destroyed\n", p->tid); + /** @todo actually destroy */ + } } /* weak to allow optimisation on risc-v, but provide fallback for future */ @@ -333,30 +298,6 @@ struct tcb *get_tcb(id_t tid) return tcbs[tid]; } -stat_t clone_rpc_maps(struct tcb *r) -{ - hard_assert(r && is_proc(r), ERR_INVAL); - struct tcb *t = r->server.next; - if (!t) - return OK; - - do { - clone_uvmem(r->proc.vmem, t->rpc.vmem); - } while ((t = t->rpc.next)); - - return OK; -} - -stat_t clone_proc_maps(struct tcb *r) -{ - hard_assert(r && is_proc(r), ERR_INVAL); - struct tcb *t = r; - while ((t = t->proc.next)) - clone_uvmem(r->proc.vmem, t->proc.vmem); - - return OK; -} - void set_return(struct tcb *t, vm_t v) { t->exec = v; diff --git a/common/uapi/ipc.c b/common/uapi/ipc.c index 13682c7..b9a435b 100644 --- a/common/uapi/ipc.c +++ b/common/uapi/ipc.c @@ -54,13 +54,13 @@ enum ipc_kind { * * @param t Thread to migrate. * @param r Process to migrate to. - * @param sd RPC stack regions to mark inaccessible. + * @param s RPC stack regions to mark inaccessible. */ static void finalize_rpc(struct tcb *t, struct tcb *r, vm_t s) { clone_uvmem(r->proc.vmem, t->rpc.vmem); set_return(t, r->callback); - attach_rpc(r, t); + reference_proc(r); t->pid = r->rid; /* make sure updates are visible when swapping to the new virtual memory */ @@ -135,6 +135,7 @@ static void leave_rpc(struct tcb *t, struct sys_ret a) while (ctx->kick) { rpc_stack = ctx->rpc_stack + BASE_PAGE_SIZE; ctx = (struct call_ctx *)(rpc_stack) - 1; + unreference_proc(get_tcb(ctx->pid)); } t->regs = ctx->regs; @@ -224,6 +225,10 @@ static void do_ipc(struct tcb *t, } r = get_rproc(r); + if (unlikely(r->dead)) { + leave_rpc(t, SYS_RET1(ERR_INVAL)); + return; + } if (unlikely(!r->callback)) { leave_rpc(t, SYS_RET1(ERR_NOINIT)); @@ -310,10 +315,7 @@ SYSCALL_DEFINE4(ipc_resp)(struct tcb *t, sys_arg_t d0, sys_arg_t d1, if (unlikely(!is_rpc(t))) return_args1(t, ERR_MISC); - /* we need the current proc before leaving the rpc */ - struct tcb *r = get_cproc(t); leave_rpc(t, SYS_RET6(OK, t->tid, d0, d1, d2, d3)); - detach_rpc(r, t); } /** diff --git a/common/vmem.c b/common/vmem.c index e90d27b..f52f43e 100644 --- a/common/vmem.c +++ b/common/vmem.c @@ -124,8 +124,7 @@ static stat_t __free_mapped_shared_region(struct tcb *t, struct mem_region *m) * * @param t Thread to work in. * @param m Memory region to free. - * @return \ref INFO_SEFF if other thread in process should be synced, \ref OK - * otherwise. + * @return \ref OK */ static stat_t __free_mapped_region(struct tcb *t, struct mem_region *m) { @@ -190,13 +189,6 @@ vm_t alloc_uvmem(struct tcb *t, size_t size, vmflags_t flags) stat_t status = OK; const vm_t v = alloc_region(&t->sp_r, size, &size, flags); const vm_t w = map_allocd_region(t->proc.vmem, v, size, flags, &status); - /** \todo this could be changed so that each thread allocated the memory - * region for itself to start with, and only when someone tries to - * access it from some other thread, is it actually cloned. Would likely - * need some major reworkings, so this is good enough for now. */ - if (is_rpc(t) && status == INFO_SEFF) - clone_rpc_maps(t); - return w; } @@ -218,8 +210,8 @@ vm_t alloc_uvpage(struct tcb *t, size_t size, vmflags_t flags, size_t *asize, return NULL; status = map_vpage(t->proc.vmem, addr, w, flags, order); - if (is_rpc(t) && status == INFO_SEFF) - clone_rpc_maps(t); + if (status) + return NULL; if (asize) *asize = actual_size; @@ -237,12 +229,6 @@ vm_t alloc_fixed_uvmem(struct tcb *t, vm_t start, size_t size, vmflags_t flags) stat_t status = OK; const vm_t v = alloc_fixed_region(&t->sp_r, start, size, &size, flags); const vm_t w = map_allocd_region(t->proc.vmem, v, size, flags, &status); - - /** @todo should probably update rpc maps even if the thread that does - * the allocation isn't in an ipc? */ - if (is_rpc(t) && status == INFO_SEFF) - clone_rpc_maps(t); - return w; } @@ -281,15 +267,15 @@ stat_t alloc_shared_uvmem(struct tcb *s, struct tcb *c, BASE_PAGE); } - if (cstatus == INFO_SEFF) - clone_rpc_maps(c); - - if (sstatus == INFO_SEFF) - clone_rpc_maps(s); - *sstart = sv; *cstart = cv; + if (sstatus) + return sstatus; + + if (cstatus) + return cstatus; + return OK; } @@ -301,8 +287,8 @@ stat_t free_uvmem(struct tcb *r, vm_t va) return ERR_NF; stat_t status = __free_mapped_region(r, m); - if (is_rpc(r) && status == INFO_SEFF) - return clone_rpc_maps(r); + if (status) + return ERR_MISC; return free_known_region(&r->sp_r, m); } @@ -319,7 +305,7 @@ stat_t alloc_uvmem_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, if (status) *status = ret; - return (ret == INFO_SEFF) ? OK : ret; + return ret; } stat_t alloc_shared_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, @@ -334,7 +320,8 @@ stat_t alloc_shared_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, ret = map_vpage(b, *offset, vaddr, flags, order); if (status) *status = ret; - return (ret == INFO_SEFF) ? OK : ret; + + return ret; } stat_t copy_allocd_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, @@ -387,5 +374,5 @@ stat_t free_uvmem_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, free_page(order, paddr); - return (ret == INFO_SEFF) ? OK : ret; + return ret; } |
