diff options
Diffstat (limited to 'common/tcb.c')
| -rw-r--r-- | common/tcb.c | 91 |
1 files changed, 69 insertions, 22 deletions
diff --git a/common/tcb.c b/common/tcb.c index 0809829..84218dc 100644 --- a/common/tcb.c +++ b/common/tcb.c @@ -63,7 +63,8 @@ static vm_t __setup_call_stack(struct tcb *t, size_t bytes) vmflags_t flags = VM_V | VM_R | VM_W | VM_U; for (size_t i = 1; i <= pages; ++i) { offset = alloc_page(BASE_PAGE, offset); - map_vpage(t->b_r, offset, PROC_STACK_TOP - BASE_PAGE_SIZE * i, + map_vpage(t->proc.vmem, offset, + PROC_STACK_TOP - BASE_PAGE_SIZE * i, flags, BASE_PAGE); } @@ -77,20 +78,21 @@ static vm_t __setup_thread_stack(struct tcb *t, size_t bytes) stat_t alloc_stacks(struct tcb *t) { - struct tcb *p = is_proc(t) ? t : t->proc; + /* get parent process */ + struct tcb *p = get_tcb(t->eid); t->thread_stack = __setup_thread_stack(p, __thread_stack_size); if (!t->thread_stack) return ERR_OOMEM; - t->call_stack = __setup_call_stack(p, __call_stack_size); - if (!t->call_stack) + /* call stack always starts at the same place in vmem. + * TODO: is this a security issue? */ + if (!__setup_call_stack(p, __call_stack_size)) return ERR_OOMEM; /* TODO: this only allows for a global stack size, what if a user wants * per thread stack sizes? */ t->thread_stack_top = t->thread_stack + __thread_stack_size; - t->call_stack_top = t->call_stack + __call_stack_size; return OK; } @@ -112,14 +114,17 @@ struct tcb *create_thread(struct tcb *p) if (likely(p)) { t->pid = p->pid; - t->proc = p; + t->proc.vmem = p->proc.vmem; } else { init_uvmem(t, UVMEM_START, UVMEM_END); + t->proc.vmem = create_vmem(); t->pid = t->tid; p = t; } - t->b_r = create_vmem(); + t->eid = t->pid; + t->rid = p->rid; + t->rpc.vmem = create_vmem(); return t; } @@ -149,13 +154,15 @@ struct tcb *create_proc(struct tcb *p) static stat_t __destroy_thread_data(struct tcb *t) { - /* free vmem */ - destroy_vmem(t->b_r); + /* free rpc vmem */ + destroy_vmem(t->rpc.vmem); /* free associated kernel stack and the structure itself */ vm_t bottom = align_down((vm_t)t, __o_size(MM_O0)); free_page(MM_O0, (pm_t)bottom); + /* TODO: free stacks */ + return OK; } @@ -168,11 +175,7 @@ stat_t destroy_thread(struct tcb *t) tcbs[t->tid] = 0; /* remove thread from process list */ - if (t->next) - t->next->prev = t->prev; - - if (t->prev) - t->prev->next = t->next; + detach_proc(get_rproc(t), t); return __destroy_thread_data(t); } @@ -182,13 +185,47 @@ 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->next);) + for (struct tcb *iter = p; (iter = iter->proc.next);) destroy_thread(iter); catastrophic_assert(destroy_uvmem(p)); return __destroy_thread_data(p); } +#define DEFINE_ATTACH(name, type) \ + stat_t name(struct tcb *r, struct tcb *t) \ + { \ + hard_assert(r != t, ERR_INVAL); \ + struct tcb *next = r->type.next; \ + t->type.next = next; \ +\ + if (next) { next->type.prev = t; } \ +\ + t->type.prev = r; \ + r->type.next = t; \ + return OK; \ + } + +DEFINE_ATTACH(attach_rpc, rpc); +DEFINE_ATTACH(attach_proc, proc); + +#define DEFINE_DETACH(name, type) \ + stat_t name(struct tcb *r, struct tcb *t) \ + { \ + MAYBE_UNUSED(r); \ + hard_assert(r != t, ERR_INVAL); \ + struct tcb *prev = t->type.prev; \ + struct tcb *next = t->type.next; \ +\ + if (prev) { prev->type.next = next; } \ + if (next) { next->type.prev = prev; } \ +\ + return OK; \ + } + +DEFINE_DETACH(detach_rpc, rpc); +DEFINE_DETACH(detach_proc, proc); + struct tcb *cur_tcb() { return cpu_tcb[cpu_id()]; @@ -197,10 +234,7 @@ struct tcb *cur_tcb() struct tcb *cur_proc() { struct tcb *t = cur_tcb(); - if (likely(is_proc(t))) - return t; - else - return t->proc; + return get_tcb(t->eid); } void use_tcb(struct tcb *t) @@ -215,12 +249,25 @@ struct tcb *get_tcb(id_t tid) return tcbs[tid]; } -stat_t clone_tcb_maps(struct tcb *r) +stat_t clone_rpc_maps(struct tcb *r) +{ + hard_assert(r && is_proc(r), ERR_INVAL); + struct tcb *t = r; + while ((t = t->rpc.next)) { + stat_t ret = clone_uvmem(r->proc.vmem, t->rpc.vmem); + if (ret) + return ret; + } + + 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->next)) { - stat_t ret = clone_uvmem(r->b_r, t->b_r); + while ((t = t->proc.next)) { + stat_t ret = clone_uvmem(r->proc.vmem, t->proc.vmem); if (ret) return ret; } |
