aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-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
6 files changed, 114 insertions, 44 deletions
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;
}