aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-04-16 20:27:46 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2022-04-16 20:27:46 +0300
commit67c9dc06ca0b5aec6430d50af9444bbe85b6deb5 (patch)
treed8f1d9b0b401f61312634b8e2d579249ea4dec34
parente71dd2d9fe1cc3a6d074f9c1894e2c5200cecdb1 (diff)
downloadkmi-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.c10
-rw-r--r--common/tcb.c109
-rw-r--r--include/apos/tcb.h19
-rw-r--r--include/apos/types.h2
-rw-r--r--include/apos/utils.h8
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)))