aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO.txt8
-rw-r--r--arch/riscv64/kernel/timer.c18
-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
-rw-r--r--include/apos/sp_tree.h10
-rw-r--r--include/apos/syscalls.h6
-rw-r--r--include/apos/timer.h47
-rw-r--r--include/apos/uapi.h91
-rw-r--r--include/arch/timer.h15
16 files changed, 383 insertions, 85 deletions
diff --git a/TODO.txt b/TODO.txt
index 24e2ab8..da68769 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -38,7 +38,12 @@ worh doing anything to.
whatever, would probably make it a bit more clean-feeling. (x)
+ Add in interrupt handling and start testing jumping back and forth.
+ Add in better tcb handling, mainly creating linked lists with all threads
-under a common process ID.
+under a common process ID. (sort of done, not sure if linked lists even
+ necessary)
++ Start implementing IRQ handling
++ Timers should use the sp_tree thing sorted by time of completion, and then
+each timer interrupt just pops the smallest value off and jumps to the
+associated program. Easy. (started)
!!! FUTURE:
+ Cache locality?
@@ -56,3 +61,4 @@ same memory (started on it)
SMP, IPC, timers a memory manager, everything else in userspace.
+ Choose between allowing the process manager to interrupt other cpus and each
cpu starts its own process manager with a timer of some sort?
++ More const correctness, possibly better assembly but don't count on it.
diff --git a/arch/riscv64/kernel/timer.c b/arch/riscv64/kernel/timer.c
new file mode 100644
index 0000000..cad811d
--- /dev/null
+++ b/arch/riscv64/kernel/timer.c
@@ -0,0 +1,18 @@
+#include <arch/timer.h>
+
+ticks_t stat_timer()
+{
+ /* TODO: read from fdt */
+ return 0;
+}
+
+void set_timer(ticks_t ticks)
+{
+ /* TODO */
+}
+
+ticks_t current_ticks()
+{
+ /* TODO */
+ return 0;
+}
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;
+}
diff --git a/include/apos/sp_tree.h b/include/apos/sp_tree.h
index 1c1525f..fe02e91 100644
--- a/include/apos/sp_tree.h
+++ b/include/apos/sp_tree.h
@@ -1,13 +1,13 @@
#ifndef SP_TREE_H
#define SP_TREE_H
-#define sp_root(r) (r.sp_r)
-#define sp_left(n) (n->left)
-#define sp_right(n) (n->right)
+#define sp_root(r) ((r)->sp_r)
+#define sp_left(n) ((n)->left)
+#define sp_right(n) ((n)->right)
#define sp_rparen(n) (sp_right(n)->parent)
#define sp_lparen(n) (sp_left(n)->parent)
-#define sp_paren(n) (n->parent)
-#define sp_gparen(n) (n->parent->parent)
+#define sp_paren(n) ((n)->parent)
+#define sp_gparen(n) ((n)->parent->parent)
#define sp_has_gparen(n) (sp_paren(n) && sp_gparen(n))
struct sp_node {
diff --git a/include/apos/syscalls.h b/include/apos/syscalls.h
index d2427cf..d9df89b 100644
--- a/include/apos/syscalls.h
+++ b/include/apos/syscalls.h
@@ -10,6 +10,10 @@ enum {
SYS_REQ_FIXMEM, /* request memory at fixed address */
SYS_FREE_MEM, /* free memory */
+ /* timers */
+ SYS_REQ_TIMER,
+ SYS_FREE_TIMER,
+
/* IPC */
/* I really should try to find my notes about the server/client
* structure of the OS, but these following syscalls are probably
@@ -28,7 +32,7 @@ enum {
/* kernel management */
SYS_CONF, /* config system parameters (stack size etc.) */
SYS_POWEROFF, /* shutdown/reboot etc. */
-}
+};
/* function declarations should be somewhere else, this file could be used in
* userspace applications as well */
diff --git a/include/apos/timer.h b/include/apos/timer.h
new file mode 100644
index 0000000..ea5bd03
--- /dev/null
+++ b/include/apos/timer.h
@@ -0,0 +1,47 @@
+#ifndef APOS_TIMER_H
+#define APOS_TIMER_H
+
+#include <apos/types.h>
+
+typedef size_t ticks_t;
+/* whichever time unit we're dealing with */
+typedef size_t tunit_t;
+
+struct timer {
+ id_t tid;
+ id_t cid;
+
+ ticks_t ticks;
+};
+
+void init_timer();
+
+/* set up timer interrupt ticks from now */
+id_t new_rel_timer(id_t tid, ticks_t ticks);
+/* set up timer interrupt at ticks (from startup I suppose) */
+id_t new_abs_timer(id_t tid, ticks_t ticks);
+
+struct timer *newest_timer();
+struct timer *find_timer(id_t cid);
+void remove_timer(struct timer *);
+
+ticks_t nsecs_to_ticks(tunit_t nsecs);
+
+static inline ticks_t usecs_to_ticks(tunit_t usecs)
+{
+ return nsecs_to_ticks(usecs * 1000);
+}
+
+static inline ticks_t msecs_to_ticks(tunit_t msecs)
+{
+ return usecs_to_ticks(msecs * 1000);
+}
+
+/* TODO: likely not a problem on 64bit systems, not sure how to handle situation on
+ * 32bit */
+static inline ticks_t secs_to_ticks(tunit_t secs)
+{
+ return msecs_to_ticks(secs * 1000);
+}
+
+#endif /* APOS_TIMER_H */
diff --git a/include/apos/uapi.h b/include/apos/uapi.h
index 74fd846..fb7dff7 100644
--- a/include/apos/uapi.h
+++ b/include/apos/uapi.h
@@ -1,29 +1,88 @@
#ifndef APOS_UAPI_H
#define APOS_UAPI_H
+#include <apos/syscalls.h>
#include <apos/vmem.h>
/* syscall function type, let's start with four arguments and see where that
* goes */
-typedef vm_t (*sys_t)(vm_t a0, vm_t a1, vm_t a2, vm_t a3);
+typedef vm_t (*sys_t)(vm_t, vm_t, vm_t, vm_t);
-vm_t sys_req_mem(vm_t size, vm_t flags, vm_t u0, vm_t u1);
-vm_t sys_req_pmem(vm_t paddr, vm_t size, vm_t flags, vm_t u0);
-vm_t sys_req_fixmem(vm_t start, vm_t size, vm_t flags, vm_t u0);
-vm_t sys_req_sharedmem(vm_t pid, vm_t start, vm_t size, vm_t flags);
-vm_t sys_free_mem(vm_t start, vm_t u0, vm_t u1, vm_t u2);
+#define SYSCALL_DECLARE(name)\
+ vm_t sys_##name(vm_t a, vm_t b, vm_t c, vm_t d);
-vm_t sys_ipc_server(vm_t callback, vm_t u0, vm_t u1, vm_t u2);
-vm_t sys_ipc_req(vm_t tgt_pid, vm_t d0, vm_t d1, vm_t d2);
-vm_t sys_ipc_resp(vm_t tgt_pid, vm_t ret, vm_t u0, vm_t u1);
+#define SYSCALL_DEFINE0(name)\
+ static vm_t __##name();\
+ vm_t sys_##name(vm_t a, vm_t b, vm_t c, vm_t d){ \
+ UNUSED(a);\
+ UNUSED(b);\
+ UNUSED(c);\
+ UNUSED(d);\
+ return __##name();\
+ }\
+ static vm_t __##name
-vm_t sys_fork(vm_t pid, vm_t u1, vm_t u2, vm_t u3);
-vm_t sys_exec(vm_t pid, vm_t bin, vm_t argc, vm_t argv);
-vm_t sys_signal(vm_t pid, vm_t signal, vm_t u0, vm_t u1);
-vm_t sys_switch(vm_t pid, vm_t u0, vm_t u1, vm_t u2);
-vm_t sys_sync(vm_t buf, vm_t size, vm_t u1, vm_t u2);
+#define SYSCALL_DEFINE1(name)\
+ static vm_t __##name(vm_t);\
+ vm_t sys_##name(vm_t a, vm_t b, vm_t c, vm_t d){ \
+ UNUSED(b);\
+ UNUSED(c);\
+ UNUSED(d);\
+ return __##name(a);\
+ }\
+ static vm_t __##name
-vm_t sys_conf(vm_t param, vm_t val, vm_t u0, vm_t u1);
-vm_t sys_poweroff(vm_t type, vm_t u0, vm_t u1, vm_t u2);
+#define SYSCALL_DEFINE2(name)\
+ static vm_t __##name(vm_t, vm_t);\
+ vm_t sys_##name(vm_t a, vm_t b, vm_t c, vm_t d){ \
+ UNUSED(c);\
+ UNUSED(d);\
+ return __##name(a, b);\
+ }\
+ static vm_t __##name
+
+#define SYSCALL_DEFINE3(name)\
+ static vm_t __##name(vm_t, vm_t, vm_t);\
+ vm_t sys_##name(vm_t a, vm_t b, vm_t c, vm_t d){ \
+ UNUSED(d);\
+ return __##name(a, b, c);\
+ }\
+ static vm_t __##name
+
+#define SYSCALL_DEFINE4(name)\
+ static vm_t __##name(vm_t, vm_t, vm_t, vm_t);\
+ vm_t sys_##name(vm_t a, vm_t b, vm_t c, vm_t d){ \
+ return __##name(a, b, c, d);\
+ }\
+ static vm_t __##name
+
+/* memory */
+SYSCALL_DECLARE(req_mem);
+SYSCALL_DECLARE(req_pmem);
+SYSCALL_DECLARE(req_fixmem);
+SYSCALL_DECLARE(req_sharedmem);
+SYSCALL_DECLARE(free_mem);
+
+/* timers */
+SYSCALL_DECLARE(req_timer);
+SYSCALL_DECLARE(free_timer);
+
+/* ipc */
+SYSCALL_DECLARE(ipc_server);
+SYSCALL_DECLARE(ipc_req);
+SYSCALL_DECLARE(ipc_resp);
+
+/* proc */
+SYSCALL_DECLARE(fork);
+SYSCALL_DECLARE(exec);
+SYSCALL_DECLARE(signal);
+SYSCALL_DECLARE(switch);
+SYSCALL_DECLARE(sync);
+
+/* conf */
+SYSCALL_DECLARE(conf);
+SYSCALL_DECLARE(poweroff);
+
+vm_t syscall_dispatch(vm_t syscall, vm_t a, vm_t b, vm_t c, vm_t d);
#endif /* APOS_UAPI_H */
diff --git a/include/arch/timer.h b/include/arch/timer.h
new file mode 100644
index 0000000..6d63565
--- /dev/null
+++ b/include/arch/timer.h
@@ -0,0 +1,15 @@
+#ifndef APOS_ARCH_TIMER_H
+#define APOS_ARCH_TIMER_H
+
+#include <apos/timer.h>
+
+/* return hardware timer frequency */
+ticks_t stat_timer();
+
+/* set up timer interrupt for absolute ticks */
+void set_timer(ticks_t ticks);
+
+/* current ticks */
+ticks_t current_ticks();
+
+#endif /* APOS_ARCH_TIMER_H */