aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--arch/riscv64/kernel/proc.c4
-rw-r--r--common/dmem.c24
-rw-r--r--common/elf.c5
-rw-r--r--common/proc.c4
-rw-r--r--common/tcb.c91
-rw-r--r--common/uapi/dispatch.c2
-rw-r--r--common/vmem.c32
-rw-r--r--include/apos/debug.h8
-rw-r--r--include/apos/tcb.h49
-rw-r--r--include/apos/utils.h1
-rw-r--r--include/arch/proc.h3
12 files changed, 152 insertions, 73 deletions
diff --git a/Makefile b/Makefile
index f676636..dad5309 100644
--- a/Makefile
+++ b/Makefile
@@ -97,7 +97,7 @@ apos.bin: init.bin kernel.bin
format:
find arch lib common include -iname '*.[ch]' |\
- uncrustify -c uncrustify.conf -q --no-backup -F -
+ uncrustify -c uncrustify.conf --no-backup -F -
.PHONY: docs
docs:
diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c
index c95021d..0eb3ad2 100644
--- a/arch/riscv64/kernel/proc.c
+++ b/arch/riscv64/kernel/proc.c
@@ -25,14 +25,14 @@ stat_t set_return(vm_t v)
return OK;
}
-stat_t prepare_thread(struct tcb *t)
+stat_t set_thread(struct tcb *t, vm_t stack)
{
/* get location of registers in memory */
/* TODO: check alignment, should be fine but just to be sure */
struct riscv_regs *r = (struct riscv_regs *)(--t);
/* insert important values into register slots */
- r->sp = (long)t->thread_stack_top;
+ r->sp = (long)stack;
r->tp = (long)t;
return OK;
diff --git a/common/dmem.c b/common/dmem.c
index 1d5608c..8bd9da3 100644
--- a/common/dmem.c
+++ b/common/dmem.c
@@ -5,6 +5,7 @@
* \todo Handle NUMA.
*/
+#include <apos/assert.h>
#include <apos/dmem.h>
static struct mem_region_root pre_ram = { 0 };
@@ -61,6 +62,8 @@ stat_t dev_free_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr,
vm_t alloc_devmem(struct tcb *t, pm_t dev_start, size_t bytes, vmflags_t flags)
{
+ hard_assert(t && is_proc(t), ERR_INVAL);
+
vm_t region = 0;
if (dev_start < __pre_top)
region = alloc_region(&pre_ram, bytes, 0, flags);
@@ -71,14 +74,22 @@ vm_t alloc_devmem(struct tcb *t, pm_t dev_start, size_t bytes, vmflags_t flags)
if (!region)
return 0;
- return map_fill_region(t->b_r, &dev_alloc_wrapper, dev_start, region,
- bytes, flags, 0);
+ stat_t status = OK;
+ const vm_t w = map_fill_region(t->proc.vmem, &dev_alloc_wrapper,
+ dev_start, region,
+ bytes, flags, &status);
+ if (is_rpc(t) && status == INFO_SEFF)
+ clone_rpc_maps(t);
+
+ return w;
}
stat_t free_devmem(struct tcb *t, vm_t dev_start)
{
+ hard_assert(t && is_proc(t), ERR_INVAL);
+
pm_t dev_paddr = 0;
- stat_vpage(t->b_r, dev_start, &dev_paddr, 0, 0);
+ stat_vpage(t->proc.vmem, dev_start, &dev_paddr, 0, 0);
if (dev_paddr >= __pre_top && dev_paddr <= __post_base)
return ERR_ADDR;
@@ -94,8 +105,11 @@ stat_t free_devmem(struct tcb *t, vm_t dev_start)
return ERR_NF;
size_t region_size = __addr(m->end - m->start);
- map_fill_region(t->b_r, &dev_free_wrapper, dev_paddr, dev_start,
- region_size, 0, 0);
+ stat_t status = OK;
+ map_fill_region(t->proc.vmem, &dev_free_wrapper, dev_paddr, dev_start,
+ region_size, 0, &status);
+ if (is_rpc(t) && status == INFO_SEFF)
+ clone_rpc_maps(t);
if (dev_paddr < __pre_top)
free_region(&pre_ram, dev_paddr);
diff --git a/common/elf.c b/common/elf.c
index b88be89..88c5ddc 100644
--- a/common/elf.c
+++ b/common/elf.c
@@ -7,6 +7,7 @@
#include <apos/vmem.h>
#include <apos/bits.h>
#include <apos/string.h>
+#include <apos/assert.h>
static uint8_t __elf_to_uvflags(uint8_t elf_flags)
{
@@ -27,6 +28,8 @@ static uint8_t __elf_to_uvflags(uint8_t elf_flags)
static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart,
size_t phnum, size_t phsize)
{
+ hard_assert(t && is_proc(t), RETURN_VOID);
+
/* TODO: take alignment into consideration? */
/* TODO: take overlapping memory regions into account, probably mostly
* by keeping track of previously allocated area and seeing if the
@@ -51,7 +54,7 @@ static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart,
uint8_t elf_flags = program_header_prop(ei_c, runner, p_flags);
uint8_t uvflags = __elf_to_uvflags(elf_flags);
- map_allocd_region(t->b_r, start, vsz, default_flags, 0);
+ map_allocd_region(t->proc.vmem, start, vsz, default_flags, 0);
vm_t vo = bin + program_header_prop(ei_c, runner, p_offset);
vm_t vfz = program_header_prop(ei_c, runner, p_filesz);
diff --git a/common/proc.c b/common/proc.c
index 3f6da6d..bf8a4d1 100644
--- a/common/proc.c
+++ b/common/proc.c
@@ -18,7 +18,7 @@ stat_t prepare_proc(struct tcb *t, vm_t bin, vm_t interp)
return ERR_INVAL;
alloc_stacks(t);
- prepare_thread(t);
+ set_thread(t, t->thread_stack_top);
set_return(entry);
return OK;
}
@@ -34,7 +34,7 @@ stat_t init_proc(void *fdt)
/* set current tcb */
use_tcb(t);
- use_vmem(t->b_r);
+ use_vmem(t->proc.vmem);
/* allocate stacks after ELF file to make sure nothing of importance
* clashes */
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;
}
diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c
index 924a0ed..df211d5 100644
--- a/common/uapi/dispatch.c
+++ b/common/uapi/dispatch.c
@@ -3,6 +3,7 @@
* Syscall dispatch.
*/
+#include <apos/debug.h>
#include <apos/uapi.h>
static const sys_t syscall_table[] = {
@@ -39,6 +40,7 @@ static const sys_t syscall_table[] = {
};
SYSCALL_DEFINE0(noop)(){
+ info("sys_noop\n");
return (struct sys_ret){ OK, 0 };
}
diff --git a/common/vmem.c b/common/vmem.c
index 74701d8..230620f 100644
--- a/common/vmem.c
+++ b/common/vmem.c
@@ -19,7 +19,7 @@ static stat_t __free_mapped_region(struct tcb *t, struct mem_region *m)
{
stat_t status = OK;
pm_t pa = __addr(m->end - m->start);
- if (unmap_freed_region(t->b_r, m->start, pa, m->flags, &status))
+ if (unmap_freed_region(t->proc.vmem, m->start, pa, m->flags, &status))
return ERR_MISC;
return status;
@@ -56,9 +56,13 @@ vm_t alloc_uvmem(struct tcb *t, size_t size, vmflags_t flags)
stat_t status = OK;
const vm_t v = alloc_region(&t->sp_r, size, &size, flags);
- const vm_t w = map_allocd_region(t->b_r, v, size, flags, &status);
- if (status == INFO_SEFF)
- clone_tcb_maps(t);
+ const vm_t w = map_allocd_region(t->proc.vmem, v, size, flags, &status);
+ /* TODO: this could be changed so that each thread allocated the memory
+ * region for itself to start with, and only when someone tries to
+ * access it from some other thread, is it actually cloned. Would likely
+ * need some major reworkings, so this is good enough for now. */
+ if (is_rpc(t) && status == INFO_SEFF)
+ clone_rpc_maps(t);
return w;
}
@@ -69,10 +73,10 @@ vm_t alloc_fixed_uvmem(struct tcb *t, vm_t start, size_t size, vmflags_t flags)
stat_t status = OK;
const vm_t v = alloc_fixed_region(&t->sp_r, start, size, &size, flags);
- const vm_t w = map_allocd_region(t->b_r, v, size, flags, &status);
+ const vm_t w = map_allocd_region(t->proc.vmem, v, size, flags, &status);
- if (status == INFO_SEFF)
- clone_tcb_maps(t);
+ if (is_rpc(t) && status == INFO_SEFF)
+ clone_rpc_maps(t);
return w;
}
@@ -85,10 +89,10 @@ vm_t alloc_shared_uvmem(struct tcb *t, size_t size, vmflags_t flags)
stat_t status = OK;
const vm_t v = alloc_region(&t->sp_r, size, &size,
flags | MR_SHARED | MR_OWNED);
- const vm_t w = map_shared_region(t->b_r, v, size, flags, &status);
+ const vm_t w = map_shared_region(t->proc.vmem, v, size, flags, &status);
- if (status == INFO_SEFF)
- clone_tcb_maps(t);
+ if (is_rpc(t) && status == INFO_SEFF)
+ clone_rpc_maps(t);
return w;
}
@@ -110,8 +114,8 @@ vm_t ref_shared_uvmem(struct tcb *t1, struct tcb *t2, vm_t va, vmflags_t flags)
vm_t runner = v;
for (; pages; --pages) {
pm_t paddr;
- stat_vpage(t1->b_r, v, &paddr, 0, 0);
- map_vpage(t2->b_r, paddr, runner, flags, MM_O0);
+ stat_vpage(t1->proc.vmem, v, &paddr, 0, 0);
+ map_vpage(t2->proc.vmem, paddr, runner, flags, MM_O0);
runner += __o_size(MM_O0);
}
@@ -128,8 +132,8 @@ stat_t free_uvmem(struct tcb *t, vm_t va)
free_region(&t->sp_r, va);
stat_t status = __free_mapped_region(t, m);
- if (status == INFO_SEFF)
- return clone_tcb_maps(t);
+ if (is_rpc(t) && status == INFO_SEFF)
+ return clone_rpc_maps(t);
return status;
}
diff --git a/include/apos/debug.h b/include/apos/debug.h
index 6d49f12..88668ff 100644
--- a/include/apos/debug.h
+++ b/include/apos/debug.h
@@ -148,11 +148,11 @@ struct dbg_info dbg_from_fdt(const void *fdt);
#define COMMON_FORMAT "[%s] %s:%d\n\t"
#define COMMON_ARGS(s) s, __FILE__, __LINE__
-#define bug(fmt, ...) dbg(COMMON_FORMAT fmt, COMMON_ARGS("BUG"), __VA_ARGS__)
-#define warn(fmt, ...) dbg(COMMON_FORMAT fmt, COMMON_ARGS("WARN"), __VA_ARGS__)
-#define info(fmt, ...) dbg(COMMON_FORMAT fmt, COMMON_ARGS("INFO"), __VA_ARGS__)
+#define bug(fmt, ...) dbg(COMMON_FORMAT fmt, COMMON_ARGS("BUG"),##__VA_ARGS__)
+#define warn(fmt, ...) dbg(COMMON_FORMAT fmt, COMMON_ARGS("WARN"),##__VA_ARGS__)
+#define info(fmt, ...) dbg(COMMON_FORMAT fmt, COMMON_ARGS("INFO"),##__VA_ARGS__)
#define error(fmt, ...) \
- dbg(COMMON_FORMAT fmt, COMMON_ARGS("ERROR"), __VA_ARGS__)
+ dbg(COMMON_FORMAT fmt, COMMON_ARGS("ERROR"),##__VA_ARGS__)
#else
diff --git a/include/apos/tcb.h b/include/apos/tcb.h
index 2b602f6..7abd432 100644
--- a/include/apos/tcb.h
+++ b/include/apos/tcb.h
@@ -11,23 +11,31 @@
#include <arch/tcb.h> /* arch-specific data */
/* process(/main) threads don't have any previous threads */
-#define is_proc(t) (!t->prev)
+#define is_proc(t) (t->rid == t->tid)
+#define is_rpc(t) (t->rid == t->pid)
+
+#define get_proc(t) (get_tcb(t->eid))
+#define get_rproc(t) (get_tcb(t->rid))
+
+/* forward declaration */
+struct tcb;
+
+struct tcb_ctx {
+ struct vmem *vmem;
+ struct tcb *next;
+ struct tcb *prev;
+};
struct tcb {
struct arch_tcbd tcbd;
- /* mapping data
- * TODO: should mem_region_root be renamed mem_root or something? feels
- * kind of clunky */
- union {
- /* if we're the main thread, we control the memory regions */
- struct mem_region_root sp_r;
- /* if we're not the main thread, we have a pointer to the main
- * thread */
- struct tcb *proc;
- };
+ /* mapping data */
+ struct mem_region_root sp_r;
+ id_t eid;
id_t pid;
+
+ id_t rid;
id_t tid;
vm_t callback;
@@ -35,15 +43,8 @@ struct tcb {
vm_t thread_stack;
vm_t thread_stack_top;
- vm_t call_stack;
- vm_t call_stack_top;
-
- /* vm root branch */
- struct vmem *b_r;
-
- /* linked list of threads in this process */
- struct tcb *next;
- struct tcb *prev;
+ struct tcb_ctx proc;
+ struct tcb_ctx rpc;
};
void init_tcbs();
@@ -54,12 +55,18 @@ struct tcb *create_proc(struct tcb *p);
stat_t destroy_thread(struct tcb *t);
stat_t destroy_proc(struct tcb *p);
+stat_t attach_rpc(struct tcb *r, struct tcb *t);
+stat_t detach_rpc(struct tcb *r, struct tcb *t);
+stat_t attach_proc(struct tcb *r, struct tcb *t);
+stat_t detach_proc(struct tcb *r, struct tcb *t);
+
struct tcb *cur_tcb();
void use_tcb(struct tcb *);
struct tcb *get_tcb(id_t tid);
-stat_t clone_tcb_maps(struct tcb *);
+stat_t clone_proc_maps(struct tcb *);
+stat_t clone_rpc_maps(struct tcb *);
stat_t alloc_stacks(struct tcb *);
#endif /* APOS_TCB_H */
diff --git a/include/apos/utils.h b/include/apos/utils.h
index 03bb801..c4a83be 100644
--- a/include/apos/utils.h
+++ b/include/apos/utils.h
@@ -27,6 +27,7 @@
#define QUOTE(x) QUOTE2(x)
#define UNUSED(x) ((void)(x))
+#define MAYBE_UNUSED(x) UNUSED(x)
#include <apos/builtin.h>
diff --git a/include/arch/proc.h b/include/arch/proc.h
index 1dcb0af..9af44c9 100644
--- a/include/arch/proc.h
+++ b/include/arch/proc.h
@@ -13,8 +13,9 @@
#endif
stat_t set_return(vm_t r);
+stat_t set_ipc(struct tcb *t, id_t pid, id_t tid);
/*TODO: should this be in arch/tcb.h or something? */
-stat_t prepare_thread(struct tcb *t);
+stat_t set_thread(struct tcb *t, vm_t stack);
stat_t run_init(struct tcb *t, void *fdt);
#endif /* APOS_ARCH_PROC_H */