diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-04-18 21:10:57 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-04-21 12:12:38 +0300 |
| commit | 7967a9ab13214543041e4408086668b4db8d3e62 (patch) | |
| tree | 4dab7b89bd9d5b5b8280877f9d8eb23a1edf1230 | |
| parent | 1ceed7525272b82c1028ebd353e65c3a63bd2714 (diff) | |
| download | kmi-7967a9ab13214543041e4408086668b4db8d3e62.tar.gz kmi-7967a9ab13214543041e4408086668b4db8d3e62.zip | |
start working on timer subsys
| -rw-r--r-- | TODO.txt | 8 | ||||
| -rw-r--r-- | arch/riscv64/kernel/timer.c | 18 | ||||
| -rw-r--r-- | common/mem_regions.c | 36 | ||||
| -rw-r--r-- | common/tcb.c | 3 | ||||
| -rw-r--r-- | common/timer.c | 124 | ||||
| -rw-r--r-- | common/uapi/conf.c | 10 | ||||
| -rw-r--r-- | common/uapi/dispatch.c | 38 | ||||
| -rw-r--r-- | common/uapi/ipc.c | 11 | ||||
| -rw-r--r-- | common/uapi/mem.c | 17 | ||||
| -rw-r--r-- | common/uapi/proc.c | 21 | ||||
| -rw-r--r-- | common/uapi/timers.c | 13 | ||||
| -rw-r--r-- | include/apos/sp_tree.h | 10 | ||||
| -rw-r--r-- | include/apos/syscalls.h | 6 | ||||
| -rw-r--r-- | include/apos/timer.h | 47 | ||||
| -rw-r--r-- | include/apos/uapi.h | 91 | ||||
| -rw-r--r-- | include/arch/timer.h | 15 |
16 files changed, 383 insertions, 85 deletions
@@ -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 */ |
