aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/mem_regions.c36
-rw-r--r--common/tcb.c3
-rw-r--r--common/timer.c124
-rw-r--r--common/uapi/conf.c10
-rw-r--r--common/uapi/dispatch.c38
-rw-r--r--common/uapi/ipc.c11
-rw-r--r--common/uapi/mem.c17
-rw-r--r--common/uapi/proc.c21
-rw-r--r--common/uapi/timers.c13
9 files changed, 211 insertions, 62 deletions
diff --git a/common/mem_regions.c b/common/mem_regions.c
index 975b6b5..e5de0e3 100644
--- a/common/mem_regions.c
+++ b/common/mem_regions.c
@@ -26,7 +26,7 @@
static struct mem_region *__insert_free_region(struct mem_region_root *r,
struct mem_region *m)
{
- struct sp_node *n = sp_root(r->free_regions), *p = NULL;
+ struct sp_node *n = sp_root(&r->free_regions), *p = NULL;
size_t start = m->start;
size_t size = m->end - m->start;
enum sp_dir d = LEFT;
@@ -59,10 +59,10 @@ static struct mem_region *__insert_free_region(struct mem_region_root *r,
}
}
- if (sp_root(r->free_regions))
- sp_insert(&sp_root(r->free_regions), p, &m->sp_n, d);
+ if (sp_root(&r->free_regions))
+ sp_insert(&sp_root(&r->free_regions), p, &m->sp_n, d);
else
- sp_root(r->free_regions) = &m->sp_n;
+ sp_root(&r->free_regions) = &m->sp_n;
return m;
}
@@ -70,7 +70,7 @@ static struct mem_region *__insert_free_region(struct mem_region_root *r,
static struct mem_region *__insert_used_region(struct mem_region_root *r,
struct mem_region *m)
{
- struct sp_node *n = sp_root(r->used_regions), *p = NULL;
+ struct sp_node *n = sp_root(&r->used_regions), *p = NULL;
vm_t start = m->start;
enum sp_dir d = LEFT;
@@ -94,10 +94,10 @@ static struct mem_region *__insert_used_region(struct mem_region_root *r,
}
}
- if (sp_root(r->used_regions))
- sp_insert(&sp_root(r->used_regions), p, &m->sp_n, d);
+ if (sp_root(&r->used_regions))
+ sp_insert(&sp_root(&r->used_regions), p, &m->sp_n, d);
else
- sp_root(r->used_regions) = &m->sp_n;
+ sp_root(&r->used_regions) = &m->sp_n;
return m;
}
@@ -129,8 +129,8 @@ static void __destroy_region(struct sp_node *n)
void destroy_region(struct mem_region_root *r)
{
- __destroy_region(sp_root(r->free_regions));
- __destroy_region(sp_root(r->used_regions));
+ __destroy_region(sp_root(&r->free_regions));
+ __destroy_region(sp_root(&r->used_regions));
}
/* interestingly this is now the main bottleneck :D
@@ -140,7 +140,7 @@ void destroy_region(struct mem_region_root *r)
* */
struct mem_region *find_used_region(struct mem_region_root *r, vm_t start)
{
- struct sp_node *n = sp_root(r->used_regions);
+ struct sp_node *n = sp_root(&r->used_regions);
while (n) {
struct mem_region *t = mem_container(n);
if (start == t->start)
@@ -184,9 +184,9 @@ struct mem_region *find_closest_used_region(struct mem_region_root *r,
{
struct mem_region *closest = 0;
size_t md = (size_t)(-1);
- struct sp_node *n = sp_root(r->used_regions);
+ struct sp_node *n = sp_root(&r->used_regions);
if (!n)
- return mem_container(sp_root(r->free_regions));
+ return mem_container(sp_root(&r->free_regions));
while (n) {
struct mem_region *t = mem_container(n);
@@ -222,7 +222,7 @@ struct mem_region *find_free_region(struct mem_region_root *r, size_t size,
*align = 0;
size_t offset = __page(po_align(__addr(size)));
struct mem_region *quick_best = 0;
- struct sp_node *n = sp_root(r->free_regions);
+ struct sp_node *n = sp_root(&r->free_regions);
while (n) {
struct mem_region *t = mem_container(n);
vm_t start = align_up(t->start, offset);
@@ -247,7 +247,7 @@ struct mem_region *find_free_region(struct mem_region_root *r, size_t size,
static vm_t __partition_region(struct mem_region_root *r, struct mem_region *m,
size_t pages, size_t align)
{
- sp_remove(&sp_root(r->free_regions), &m->sp_n);
+ sp_remove(&sp_root(&r->free_regions), &m->sp_n);
vm_t pre_start = m->start;
vm_t pre_end = pre_start + align;
@@ -353,7 +353,7 @@ static void __try_coalesce_prev(struct mem_region_root *r, struct mem_region *m)
if (m->prev)
m->prev->next = m;
- sp_remove(&sp_root(r->free_regions), &p->sp_n);
+ sp_remove(&sp_root(&r->free_regions), &p->sp_n);
free_mem_node(p);
m = m->prev;
@@ -376,7 +376,7 @@ static void __try_coalesce_next(struct mem_region_root *r, struct mem_region *m)
if (m->next)
m->next->prev = m;
- sp_remove(&sp_root(r->free_regions), &n->sp_n);
+ sp_remove(&sp_root(&r->free_regions), &n->sp_n);
free_mem_node(n);
m = m->next;
@@ -400,7 +400,7 @@ stat_t free_region(struct mem_region_root *r, vm_t start)
if (!m)
return ERR_NF;
- sp_remove(&sp_root(r->used_regions), &m->sp_n);
+ sp_remove(&sp_root(&r->used_regions), &m->sp_n);
mark_region_unused(m->flags);
__try_coalesce_regions(r, m);
diff --git a/common/tcb.c b/common/tcb.c
index 43c5969..4a69df6 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -24,7 +24,7 @@ void init_tcbs()
/* 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);
+ tcbs = (struct tcb **)alloc_page(MM_O1, 0);
num_tids = __o_size(MM_O1) / sizeof(struct tcb *);
memset(tcbs, 0, __o_size(MM_O1));
}
@@ -57,6 +57,7 @@ struct tcb *new_thread()
struct tcb *t = (struct tcb *)get_node(&root);
t->tid = __alloc_tid(t);
+ return t;
}
void destroy_thread(struct tcb *t)
diff --git a/common/timer.c b/common/timer.c
new file mode 100644
index 0000000..b48e455
--- /dev/null
+++ b/common/timer.c
@@ -0,0 +1,124 @@
+#include <apos/sp_tree.h>
+#include <apos/string.h>
+#include <apos/nodes.h>
+#include <apos/utils.h>
+#include <apos/timer.h>
+#include <arch/timer.h>
+#include <arch/cpu.h>
+
+static ticks_t ticks_per_sec = 0;
+static struct sp_root cpu_timers[MAX_CPUS] = {0};
+static struct node_root node_root;
+
+struct timer_node {
+ struct sp_node sp_n;
+ struct timer timer;
+};
+
+#define timer_container(ptr)\
+ container_of(ptr, struct timer_node, sp_n)
+
+#define timer_node_container(ptr)\
+ container_of(ptr, struct timer_node, timer)
+
+static struct sp_root *__cpu_timers()
+{
+ return &cpu_timers[cpu_id()];
+}
+
+void init_timer()
+{
+ ticks_per_sec = stat_timer();
+ init_nodes(&node_root, sizeof(struct timer_node));
+}
+
+static id_t __insert_timer(struct timer_node *ti)
+{
+ struct sp_root *root = __cpu_timers();
+ struct sp_node *n = sp_root(root), *p = NULL;
+ enum sp_dir d;
+ while (n) {
+ struct timer_node *t = container_of(n, struct timer_node, sp_n);
+ if (ti->timer.cid == t->timer.cid)
+ ti->timer.cid--;
+
+ p = n;
+
+ if (ti->timer.cid < t->timer.cid) {
+ n = sp_left(n);
+ d = LEFT;
+ } else {
+ n = sp_right(n);
+ d = RIGHT;
+ }
+ }
+
+ if (sp_root(root))
+ sp_insert(&sp_root(root), p, &ti->sp_n, d);
+ else
+ sp_root(root) = &ti->sp_n;
+
+ return ti->timer.cid;
+}
+
+/* ticks is absolute */
+static id_t __new_timer(id_t tid, ticks_t ticks)
+{
+ struct timer_node *ti = (struct timer_node *)get_node(&node_root);
+ ti->timer.ticks = ticks;
+ ti->timer.cid = ticks;
+ ti->timer.tid = tid;
+ return __insert_timer(ti);
+}
+
+/* these are likely not perfectly accurate timers due to some random delay from
+ * function calls etc, but probably good enough. */
+id_t new_rel_timer(id_t tid, ticks_t ticks)
+{
+ return new_abs_timer(tid, ticks + current_ticks());
+}
+
+id_t new_abs_timer(id_t tid, ticks_t ticks)
+{
+ id_t id = __new_timer(tid, ticks);
+ set_timer(ticks);
+ return id;
+}
+
+struct timer *newest_timer()
+{
+ struct sp_node *t = sp_first(sp_root(__cpu_timers()));
+ return &timer_container(t)->timer;
+}
+
+struct timer *find_timer(id_t cid)
+{
+ struct sp_node *n = sp_root(__cpu_timers());
+ while (n) {
+ struct timer_node *t = timer_container(n);
+ if (t->timer.cid == cid)
+ return &t->timer;
+
+ if (t->timer.cid < cid)
+ n = sp_left(n);
+ else
+ n = sp_right(n);
+ }
+
+ return 0;
+}
+
+void remove_timer(struct timer *t)
+{
+ if (!t)
+ return;
+
+ struct sp_node *n = &timer_node_container(t)->sp_n;
+ sp_remove(&sp_root(__cpu_timers()), n);
+}
+
+/* TODO: does this overflow too early? */
+ticks_t nsecs_to_ticks(tunit_t nsecs)
+{
+ return (nsecs * ticks_per_sec) / 1000000000;
+}
diff --git a/common/uapi/conf.c b/common/uapi/conf.c
index 7acb540..3002fc2 100644
--- a/common/uapi/conf.c
+++ b/common/uapi/conf.c
@@ -5,23 +5,17 @@
size_t __proc_stack_size = SZ_2M;
size_t __call_stack_size = SZ_2M;
-vm_t sys_conf(vm_t param, vm_t val, vm_t u0, vm_t u1)
+SYSCALL_DEFINE2(conf)(vm_t param, vm_t val)
{
- UNUSED(u0);
- UNUSED(u1);
UNUSED(param);
UNUSED(val);
-
/* no parameters supported atm */
return OK;
}
-vm_t sys_poweroff(vm_t type, vm_t u0, vm_t u1, vm_t u2)
+SYSCALL_DEFINE1(poweroff)(vm_t type)
{
- UNUSED(u0);
- UNUSED(u1);
- UNUSED(u2);
switch (type) {
case SHUTDOWN:
case COLD_REBOOT:
diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c
new file mode 100644
index 0000000..3b03c43
--- /dev/null
+++ b/common/uapi/dispatch.c
@@ -0,0 +1,38 @@
+#include <apos/uapi.h>
+
+static const sys_t syscall_table[] = {
+ /* mem */
+ [SYS_REQ_MEM] = sys_req_mem,
+ [SYS_REQ_PMEM] = sys_req_pmem,
+ [SYS_REQ_FIXMEM] = sys_req_fixmem,
+ [SYS_FREE_MEM] = sys_free_mem,
+
+ /* timers */
+ [SYS_REQ_TIMER] = sys_req_timer,
+ [SYS_FREE_TIMER] = sys_free_timer,
+
+ /* ipc */
+ [SYS_IPC_SERVER] = sys_ipc_server,
+ [SYS_IPC_REQ] = sys_ipc_req,
+ [SYS_IPC_RESP] = sys_ipc_resp,
+
+ /* proc */
+ [SYS_FORK] = sys_fork,
+ [SYS_EXEC] = sys_exec,
+ [SYS_SIGNAL] = sys_signal,
+ [SYS_SWITCH] = sys_switch,
+ [SYS_SYNC] = sys_sync,
+
+ /* conf */
+ [SYS_CONF] = sys_conf,
+ [SYS_POWEROFF] = sys_poweroff,
+};
+
+vm_t syscall_dispatch(vm_t syscall, vm_t a, vm_t b, vm_t c, vm_t d)
+{
+ sys_t call = syscall_table[syscall];
+ if (!call)
+ return ERR_INVAL;
+
+ return call(a, b, c, d);
+}
diff --git a/common/uapi/ipc.c b/common/uapi/ipc.c
index a3b29f8..3244100 100644
--- a/common/uapi/ipc.c
+++ b/common/uapi/ipc.c
@@ -1,11 +1,8 @@
#include <apos/uapi.h>
#include <apos/tcb.h>
-vm_t sys_ipc_server(vm_t callback, vm_t u0, vm_t u1, vm_t u2)
+SYSCALL_DEFINE1(ipc_server)(vm_t callback)
{
- UNUSED(u0);
- UNUSED(u1);
- UNUSED(u2);
struct tcb *r = cur_tcb();
if (r->callback) /* server can't be reinitialized */
return 1;
@@ -14,17 +11,15 @@ vm_t sys_ipc_server(vm_t callback, vm_t u0, vm_t u1, vm_t u2)
return 0;
}
-vm_t sys_ipc_req(vm_t pid, vm_t d0, vm_t d1, vm_t d2)
+SYSCALL_DEFINE4(ipc_req)(vm_t pid, vm_t d0, vm_t d1, vm_t d2)
{
struct tcb *t = get_tcb(pid);
/* something like jump_to_callback(t, d0, d1, d2) */
return 0;
}
-vm_t sys_ipc_resp(vm_t pid, vm_t ret, vm_t u0, vm_t u1)
+SYSCALL_DEFINE2(ipc_resp)(vm_t pid, vm_t ret)
{
- UNUSED(u0);
- UNUSED(u1);
struct tcb *r = get_tcb(pid);
/* something like return_from_callback(t, r) */
return 0; /* oh yeah probably unreachable? */
diff --git a/common/uapi/mem.c b/common/uapi/mem.c
index f54131f..d4893b3 100644
--- a/common/uapi/mem.c
+++ b/common/uapi/mem.c
@@ -3,27 +3,21 @@
#include <apos/vmem.h>
#include <apos/dmem.h>
-vm_t sys_req_mem(vm_t size, vm_t flags, vm_t u0, vm_t u1)
+SYSCALL_DEFINE2(req_mem)(vm_t size, vm_t flags)
{
- UNUSED(u0);
- UNUSED(u1);
/* proc_tcb should give the tcb of the TID currently running */
struct tcb *r = cur_tcb();
return alloc_uvmem(r, size, flags);
}
-vm_t sys_req_fixmem(vm_t start, vm_t size, vm_t flags, vm_t u0)
+SYSCALL_DEFINE3(req_fixmem)(vm_t start, vm_t size, vm_t flags)
{
- UNUSED(u0);
struct tcb *r = cur_tcb();
return alloc_fixed_uvmem(r, start, size, flags);
}
-vm_t sys_free_mem(vm_t start, vm_t u0, vm_t u1, vm_t u2)
+SYSCALL_DEFINE1(free_mem)(vm_t start)
{
- UNUSED(u0);
- UNUSED(u1);
- UNUSED(u2);
struct tcb *r = cur_tcb();
if (start > __pre_top && start < __post_base)
free_uvmem(r, start);
@@ -33,9 +27,8 @@ vm_t sys_free_mem(vm_t start, vm_t u0, vm_t u1, vm_t u2)
return 0;
}
-vm_t sys_req_pmem(vm_t paddr, vm_t size, vm_t flags, vm_t u0)
+SYSCALL_DEFINE3(req_pmem)(vm_t paddr, vm_t size, vm_t flags)
{
- UNUSED(u0);
/* this will require some pondering, but essentially this syscall should
* only be used for device access, so any addresses requested should be
* outside the RAM area, and I'll probably have to implement some method
@@ -45,7 +38,7 @@ vm_t sys_req_pmem(vm_t paddr, vm_t size, vm_t flags, vm_t u0)
return alloc_devmem(r, paddr, size, flags);
}
-vm_t sys_req_sharedmem(vm_t pid, vm_t start, vm_t size, vm_t flags)
+SYSCALL_DEFINE4(req_sharedmem)(vm_t pid, vm_t start, vm_t size, vm_t flags)
{
/* take memory in PID's vaddr and map it somewhere in our own memory
* region.
diff --git a/common/uapi/proc.c b/common/uapi/proc.c
index e4673b5..7c0a69d 100644
--- a/common/uapi/proc.c
+++ b/common/uapi/proc.c
@@ -10,42 +10,33 @@
* would have to periodically ask the kernel about all threads it is aware of
* via sys_sync. Dunno.
*/
-vm_t sys_fork(vm_t pid, vm_t u0, vm_t u1, vm_t u2)
+SYSCALL_DEFINE1(fork)(vm_t pid)
{
- UNUSED(u0);
- UNUSED(u1);
- UNUSED(u2);
+ /* fork might not actually even need pid...? */
/* TODO: create new thread in the same process family */
return 0;
}
-vm_t sys_exec(vm_t pid, vm_t bin, vm_t argc, vm_t argv)
+SYSCALL_DEFINE4(exec)(vm_t pid, vm_t bin, vm_t argc, vm_t argv)
{
/* TODO: execute new process */
return 0;
}
-vm_t sys_signal(vm_t pid, vm_t signal, vm_t u0, vm_t u1)
+SYSCALL_DEFINE2(signal)(vm_t pid, vm_t signal)
{
- UNUSED(u0);
- UNUSED(u1);
/* TODO: signals? */
return 0;
}
-vm_t sys_switch(vm_t pid, vm_t u0, vm_t u1, vm_t u2)
+SYSCALL_DEFINE1(switch)(vm_t pid)
{
- UNUSED(u0);
- UNUSED(u1);
- UNUSED(u2);
/* TODO: switch to process */
return 0;
}
-vm_t sys_sync(vm_t buf, vm_t size, vm_t u0, vm_t u1)
+SYSCALL_DEFINE2(sync)(vm_t buf, vm_t size)
{
- UNUSED(u0);
- UNUSED(u1);
/* check that only the process manager can use this syscall, otherwise
* just dump process info into the buffer (I guess, not sure if this
* will be quite required */
diff --git a/common/uapi/timers.c b/common/uapi/timers.c
new file mode 100644
index 0000000..1dfc8bf
--- /dev/null
+++ b/common/uapi/timers.c
@@ -0,0 +1,13 @@
+#include <apos/uapi.h>
+
+SYSCALL_DEFINE1(req_timer)(vm_t ticks)
+{
+ /* TODO */
+ return 0;
+}
+
+SYSCALL_DEFINE1(free_timer)(vm_t cid)
+{
+ /* TODO */
+ return 0;
+}