diff options
Diffstat (limited to 'common/tcb.c')
| -rw-r--r-- | common/tcb.c | 98 |
1 files changed, 82 insertions, 16 deletions
diff --git a/common/tcb.c b/common/tcb.c index 212e20f..32c31e1 100644 --- a/common/tcb.c +++ b/common/tcb.c @@ -2,6 +2,7 @@ #include <arch/cpu.h> #include <apos/mem.h> #include <apos/pmem.h> +#include <apos/vmem.h> #include <apos/nodes.h> #include <apos/types.h> #include <apos/assert.h> @@ -12,7 +13,6 @@ static id_t start_tid; static size_t num_tids; -static struct node_root root; static struct tcb **tcbs; /* if we ever support systems with massive amounts of cpus, this should probably @@ -31,8 +31,7 @@ void init_tcbs() void destroy_tcbs() { - destroy_nodes(&root); - free_page(MM_O2, (pm_t)tcbs); + free_page(MM_O1, (pm_t)tcbs); } static id_t __alloc_tid(struct tcb *t) @@ -50,10 +49,9 @@ static id_t __alloc_tid(struct tcb *t) return ERR_NF; } -struct tcb *new_thread() +struct tcb *create_thread(struct tcb *p) { - if (unlikely(!tcbs)) - return 0; + hard_assert(tcbs, 0); vm_t bottom = alloc_page(MM_O0, 0); /* move tcb to top of kernel stack, keeping alignment in check @@ -67,20 +65,80 @@ struct tcb *new_thread() tcbs[tid] = t; t->tid = tid; + if (p) { + t->pid = p->pid; + t->proc = p; + } else { + t->pid = t->tid; + } + return t; } -void destroy_thread(struct tcb *t) +static stat_t __clone_proc(struct tcb *p, struct tcb *n) +{ + /* TODO: clone memory regions, and mark them MR_COW, as well as copy + * bm_branch tree but with VM_W off, also at some point write COW + * handler */ + return OK; +} + +struct tcb *create_proc(struct tcb *p) { - if (unlikely(!tcbs)) - return; + hard_assert(tcbs, 0); - /* remove thread id from list */ - tcbs[t->tid] = 0; + /* create a new thread outside the current process */ + struct tcb *n = create_thread(0); + n->b_r = create_vmem(); - /* free associated kernel stack */ + if (likely(p)) + __clone_proc(p, n); /* we have a parent thread */ + else + init_uvmem(n, UVMEM_START, UVMEM_END); + + return n; +} + +static stat_t __destroy_thread_data(struct tcb *t) +{ + /* free vm_branch */ + destroy_vmem(t->b_r); + + /* 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); + + return OK; +} + +stat_t destroy_thread(struct tcb *t) +{ + hard_assert(tcbs, ERR_NOINIT); + hard_assert(!is_proc(t), ERR_INVAL); + + /* remove thread id from list */ + 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; + + return __destroy_thread_data(t); +} + +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);) + destroy_thread(iter); + + catastrophic_assert(destroy_uvmem(p)); + return __destroy_thread_data(p); } struct tcb *cur_tcb() @@ -88,6 +146,15 @@ struct tcb *cur_tcb() return cpu_tcb[cpu_id()]; } +struct tcb *cur_proc() +{ + struct tcb *t = cur_tcb(); + if (likely(is_proc(t))) + return t; + else + return t->proc; +} + void use_tcb(struct tcb *t) { cpu_tcb[cpu_id()] = t; @@ -95,18 +162,17 @@ void use_tcb(struct tcb *t) struct tcb *get_tcb(id_t tid) { - if (unlikely(!tcbs)) - return 0; + hard_assert(tcbs, 0); return tcbs[tid]; } stat_t clone_tcb_maps(struct tcb *r) { - hard_assert(r && !r->parent, ERR_INVAL); + hard_assert(r && is_proc(r), ERR_INVAL); struct tcb *t = r; while ((t = t->next)) { - stat_t ret = clone_vmbranch(r->b_r, t->b_r); + stat_t ret = clone_uvmem(r->b_r, t->b_r); if (ret) return ret; } |
