aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/dmem.c11
-rw-r--r--common/tcb.c97
-rw-r--r--common/uapi/ipc.c12
-rw-r--r--common/vmem.c43
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;
}