diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-04-16 20:27:46 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-04-16 20:27:46 +0300 |
| commit | 67c9dc06ca0b5aec6430d50af9444bbe85b6deb5 (patch) | |
| tree | d8f1d9b0b401f61312634b8e2d579249ea4dec34 | |
| parent | e71dd2d9fe1cc3a6d074f9c1894e2c5200cecdb1 (diff) | |
| download | kmi-67c9dc06ca0b5aec6430d50af9444bbe85b6deb5.tar.gz kmi-67c9dc06ca0b5aec6430d50af9444bbe85b6deb5.zip | |
initial thread id handling
+ At least initial in the sense that this seems like the smartest way to
handle things, that is.
| -rw-r--r-- | common/proc.c | 10 | ||||
| -rw-r--r-- | common/tcb.c | 109 | ||||
| -rw-r--r-- | include/apos/tcb.h | 19 | ||||
| -rw-r--r-- | include/apos/types.h | 2 | ||||
| -rw-r--r-- | include/apos/utils.h | 8 |
5 files changed, 90 insertions, 58 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]; } diff --git a/include/apos/tcb.h b/include/apos/tcb.h index b2e38a0..7ed07c5 100644 --- a/include/apos/tcb.h +++ b/include/apos/tcb.h @@ -6,24 +6,35 @@ #include <tcb.h> /* arch-specific data */ struct tcb { - struct sp_node sp_n; - struct mem_region_root sp_r; struct arch_tcbd tcbd; - id_t pid; + /* mapping data + * TODO: should mem_region_root be renamed mem_root or something? feels + * kind of clunky */ + struct mem_region_root sp_r; + id_t tid; vm_t callback; vm_t proc_stack; vm_t call_stack; + /* entry point */ vm_t entry; + /* vm root branch */ struct vm_branch *b_r; }; -stat_t threads_insert(struct tcb *t); +void init_tcbs(); +void destroy_tcbs(); + +struct tcb *new_thread(); +void destroy_thread(struct tcb *); + struct tcb *cur_tcb(); +void use_tcb(struct tcb *); + struct tcb *get_tcb(id_t tid); #endif /* APOS_TCB_H */ diff --git a/include/apos/types.h b/include/apos/types.h index 48972da..2f06ec4 100644 --- a/include/apos/types.h +++ b/include/apos/types.h @@ -184,6 +184,8 @@ typedef uint_fast16_t vmflags_t; /* negative error codes are reserved for general usage, positive error codes are * allowed to be function-specific. */ enum { + ERR_NOINIT = -7, /* not initialized */ + ERR_INVAL = -6, /* invalid value */ ERR_EXT = -5, /* already exists */ ERR_OOMEM = -4, /* out of memory */ ERR_ADDR = -3, /* illegal address */ diff --git a/include/apos/utils.h b/include/apos/utils.h index e060c44..af0534a 100644 --- a/include/apos/utils.h +++ b/include/apos/utils.h @@ -31,6 +31,14 @@ #define offsetof(type, member) ((size_t) & ((type *)0)->member) #endif +#if __has_builtin(__builtin_expect) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif + #define container_of(ptr, type, member) \ ((type *)((char *)(ptr)-offsetof(type, member))) |
