diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/proc.c | 10 | ||||
| -rw-r--r-- | common/tcb.c | 109 |
2 files changed, 65 insertions, 54 deletions
diff --git a/common/proc.c b/common/proc.c index 9f89b7f..e0b8c70 100644 --- a/common/proc.c +++ b/common/proc.c @@ -27,17 +27,13 @@ static vm_t setup_proc_stack(struct tcb *t, size_t bytes) stat_t init_proc(void *fdt, struct vm_branch *b) { + init_tcbs(); + /* todo: cleanup or something */ - struct tcb *t = (struct tcb *)alloc_page(BASE_PAGE, 0); + struct tcb *t = new_thread(); if (!t) return ERR_OOMEM; - - memset(t, 0, sizeof(struct tcb)); t->b_r = b; - t->pid = 0; - t->tid = 0; - - threads_insert(t); init_uvmem(t, UVMEM_START, UVMEM_END); diff --git a/common/tcb.c b/common/tcb.c index cd946bd..43c5969 100644 --- a/common/tcb.c +++ b/common/tcb.c @@ -1,74 +1,89 @@ #include <apos/tcb.h> -#include <apos/utils.h> -#include <apos/sp_tree.h> #include <arch/cpu.h> +#include <apos/mem.h> +#include <apos/pmem.h> +#include <apos/nodes.h> +#include <apos/types.h> +#include <apos/string.h> -static struct sp_root t_root = (struct sp_root){ 0 }; -static struct tcb *__tcb_cache[MAX_CPUS] = { 0 }; +/* arguably exessively many globals... */ +static id_t start_tid; +static size_t num_tids; -#define tcb_container(x) container_of(x, struct tcb, sp_n) +static struct node_root root; +static struct tcb **tcbs; -stat_t threads_insert(struct tcb *t) -{ - if (!sp_root(t_root)) { - sp_root(t_root) = &t->sp_n; - return OK; - } +/* if we ever support systems with massive amounts of cpus, this should probably + * be allocated at runtime */ +static struct tcb *cpu_tcb[MAX_CPUS] = {0}; - struct sp_node *n = sp_root(t_root), *p = NULL; - enum sp_dir d = LEFT; +void init_tcbs() +{ + /* assumption: init_tcb called after memory subsystem is initialized */ + init_nodes(&root, sizeof(struct tcb)); + /* MM_O1 is 2MiB on riscv64, so 262144 different possible thread ids. + * Should be enough, if we're really strapped for memory I might try + * something smaller but this is fine for now. */ + tcbs = alloc_page(MM_O1, 0); + num_tids = __o_size(MM_O1) / sizeof(struct tcb *); + memset(tcbs, 0, __o_size(MM_O1)); +} - while (n) { - struct tcb *tc = tcb_container(n); - p = n; +void destroy_tcbs() +{ + destroy_nodes(&root); + free_page(MM_O2, (pm_t)tcbs); +} - if (t->tid < tc->tid) { - n = sp_left(n); - d = LEFT; - } +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]) + continue; - else { - n = sp_right(n); - d = RIGHT; - } + tcbs[i] = t; + start_tid = i + 1; + return i; } - sp_insert(&sp_root(t_root), p, &t->sp_n, d); - return OK; + return ERR_NF; } -struct tcb *threads_find(id_t tid) +struct tcb *new_thread() { - struct sp_node *n = sp_root(t_root); + if (unlikely(!tcbs)) + return 0; - while (n) { - struct tcb *t = tcb_container(n); - - if (t->tid == tid) - return t; + struct tcb *t = (struct tcb *)get_node(&root); + t->tid = __alloc_tid(t); +} - if (t->tid < tid) - n = sp_left(n); - else - n = sp_right(n); - } +void destroy_thread(struct tcb *t) +{ + if (unlikely(!tcbs)) + return; - return 0; + /* remove thread id from list */ + tcbs[t->tid] = 0; + /* free node associated with tcb */ + free_node(&root, t); } -struct tcb *get_tcb(id_t pid) +struct tcb *cur_tcb() { - /* TODO: figure out how exactly thread IDs are related to process IDs, - * and figure out mapping between them. */ - return 0; + return cpu_tcb[cpu_id()]; } -struct tcb *cur_tcb() +void use_tcb(struct tcb *t) { - return __tcb_cache[cpu_id()]; + cpu_tcb[cpu_id()] = t; } -void set_tcb(struct tcb *t) +struct tcb *get_tcb(id_t tid) { - __tcb_cache[cpu_id()] = t; + if (unlikely(!tcbs)) + return 0; + + return tcbs[tid]; } |
