aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-06-12 16:18:47 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2022-06-12 16:18:47 +0300
commit62fc51338d7259c2ea39f38bd8c7d9552e9b2002 (patch)
tree87eb670ed58b3ce0d5c0e2ad39f5c633d9e10e40 /common
parent6c529c5c6c2d016d77b143171c5e27fbec0d2bfd (diff)
downloadkmi-62fc51338d7259c2ea39f38bd8c7d9552e9b2002.tar.gz
kmi-62fc51338d7259c2ea39f38bd8c7d9552e9b2002.zip
doxygen shows no warnings
+ Does not mean documentation is done, but it's a nice little achievement nonetheless.
Diffstat (limited to 'common')
-rw-r--r--common/dmem.c30
-rw-r--r--common/elf.c40
-rw-r--r--common/main.c9
-rw-r--r--common/mem_nodes.c1
-rw-r--r--common/mem_regions.c77
-rw-r--r--common/nodes.c35
-rw-r--r--common/tcb.c64
-rw-r--r--common/timer.c43
-rw-r--r--common/uapi/conf.c24
-rw-r--r--common/uapi/dispatch.c6
-rw-r--r--common/uapi/ipc.c34
-rw-r--r--common/uapi/mem.c83
-rw-r--r--common/uapi/proc.c41
-rw-r--r--common/uapi/timers.c58
-rw-r--r--common/vmem.c12
15 files changed, 526 insertions, 31 deletions
diff --git a/common/dmem.c b/common/dmem.c
index 88b06fd..98b58fd 100644
--- a/common/dmem.c
+++ b/common/dmem.c
@@ -11,8 +11,12 @@
#include <apos/assert.h>
#include <apos/dmem.h>
+/** Region before RAM. */
static struct mem_region_root pre_ram = { 0 };
+
+/** Region after RAM. */
static struct mem_region_root post_ram = { 0 };
+
pm_t __pre_base = 0;
pm_t __pre_top = 0;
pm_t __post_base = 0;
@@ -37,6 +41,19 @@ stat_t init_devmem(pm_t ram_base, pm_t ram_top)
return OK;
}
+/**
+ * Device virtual memory worker callback for \ref map_fill_region().
+ *
+ * @param b Virtual memory to work in.
+ * @param offset Hint for \ref alloc_page().
+ * @param vaddr Current virtual address.
+ * @param flags Flags of region.
+ * @param order Suggested page order.
+ * @param data Pointer to \ref stat_t.
+ * @return \see alloc_uvmem_wrapper().
+ *
+ * \see alloc_uvmem_wrapper().
+ */
static stat_t dev_alloc_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr,
vmflags_t flags, enum mm_order order,
void *data)
@@ -48,6 +65,19 @@ static stat_t dev_alloc_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr,
return OK;
}
+/**
+ * Device virtual memory freeing worker callback for \ref map_fill_region().
+ *
+ * @param b Virtual memory to work in.
+ * @param offset Hint for \ref alloc_page().
+ * @param vaddr Current virtual address.
+ * @param flags Flags of region.
+ * @param order Suggested page order.
+ * @param data Pointer to \ref stat_t.
+ * @return \see alloc_uvmem_wrapper().
+ *
+ * \see alloc_uvmem_wrapper().
+ */
static stat_t dev_free_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr,
vmflags_t flags, enum mm_order order, void *data)
{
diff --git a/common/elf.c b/common/elf.c
index 977906f..fcd6e85 100644
--- a/common/elf.c
+++ b/common/elf.c
@@ -12,6 +12,12 @@
#include <apos/string.h>
#include <apos/assert.h>
+/**
+ * Convert ELF flags to page flags.
+ *
+ * @param elf_flags ELF flags to convert.
+ * @return Corresponding page flags.
+ */
static uint8_t __elf_to_uvflags(uint8_t elf_flags)
{
uint8_t uvflags = VM_V | VM_U;
@@ -27,7 +33,16 @@ static uint8_t __elf_to_uvflags(uint8_t elf_flags)
return uvflags;
}
-/* useful bit of info: all segments are sorted in ascending order of p_vaddr */
+/**
+ * Map ELF executable.
+ *
+ * @param t Thread space to work in.
+ * @param bin Address of binary to map.
+ * @param ei_c ELF identity class.
+ * @param phstart Program header start.
+ * @param phnum Number of program header entries.
+ * @param phsize Size of page header entry.
+ */
static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart,
size_t phnum, size_t phsize)
{
@@ -40,6 +55,7 @@ static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart,
/** \todo check if p_memsz is larger than p_filesz, the segment should be
* filled with zeroes. */
/** \todo in general, make this a low more clean. */
+ /* useful bit of info: all segments are sorted in ascending order of p_vaddr */
vm_t runner = phstart;
vmflags_t default_flags = VM_V | VM_R | VM_W | VM_X | VM_U;
for (size_t i = 0; i < phnum; ++i, runner += phsize) {
@@ -74,6 +90,17 @@ static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart,
}
}
+/**
+ * Map ELF dynamic object.
+ *
+ * @param t Thread space to work in.
+ * @param bin Address of binary to map.
+ * @param ei_c ELF identity class.
+ * @param phstart Program header start.
+ * @param phnum Number of program header entries.
+ * @param phsize Size of page header entry.
+ * @return Base of dynamic mapping.
+ */
static vm_t __map_dyn(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart,
size_t phnum, size_t phsize)
{
@@ -82,6 +109,17 @@ static vm_t __map_dyn(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart,
* hacky, I know.*/
}
+/**
+ * Map binary and optional interpreter.
+ *
+ * \todo Implement interpeter handling.
+ *
+ * @param t Thread space to work in.
+ * @param ei_c ELF identity class. (Of binary, should do one for interp?)
+ * @param elf ELF binary.
+ * @param interp ELF interpeter.
+ * @return Entry address.
+ */
static vm_t __prepare_proc(struct tcb *t, uint8_t ei_c, vm_t elf, vm_t interp)
{
short e_type = elf_header_prop(ei_c, elf, e_type);
diff --git a/common/main.c b/common/main.c
index fa5434c..fb5d26e 100644
--- a/common/main.c
+++ b/common/main.c
@@ -17,6 +17,15 @@
#include <arch/irq.h>
#include <libfdt.h>
+/**
+ * Boot entry of kernel actual.
+ *
+ * Sets up all kernel subsystems and jumps into \c init program, does not
+ * return.
+ *
+ * @param fdt Global FDT pointer.
+ * @return Should not.
+ */
void __main main(void *fdt)
{
/* dbg uses direct mapping at this point */
diff --git a/common/mem_nodes.c b/common/mem_nodes.c
index ffa089f..918ee67 100644
--- a/common/mem_nodes.c
+++ b/common/mem_nodes.c
@@ -16,6 +16,7 @@
#include <apos/string.h>
#include <apos/mem_nodes.h>
+/** Memory node subsystem instance. */
static struct node_root root;
void init_mem_nodes()
diff --git a/common/mem_regions.c b/common/mem_regions.c
index 3729caf..0101ac2 100644
--- a/common/mem_regions.c
+++ b/common/mem_regions.c
@@ -13,7 +13,18 @@
#include <apos/bits.h>
#include <apos/mem.h>
+/**
+ * Readability wrapper for marking region used.
+ *
+ * @param r Region flags to set.
+ */
#define mark_region_used(r) set_bit(r, MR_USED)
+
+/**
+ * Readability wrapper for marking region unused.
+ *
+ * @param r Region flags to clear.
+ */
#define mark_region_unused(r) clear_bit(r, MR_USED)
/* pretty major slowdown when we get to some really massive numbers, not
@@ -32,6 +43,14 @@
* maybe not even anything with sp_trees but more a weakness of binary trees in
* general?
*/
+
+/**
+ * Insert free memory region.
+ *
+ * @param r Memory region root to insert \c m into.
+ * @param m Free memory region to insert.
+ * @return \c m.
+ */
static struct mem_region *__insert_free_region(struct mem_region_root *r,
struct mem_region *m)
{
@@ -76,6 +95,13 @@ static struct mem_region *__insert_free_region(struct mem_region_root *r,
return m;
}
+/**
+ * Insert used memory region.
+ *
+ * @param r Memory region root to insert \c m into.
+ * @param m Memory region to insert.
+ * @return \c m.
+ */
static struct mem_region *__insert_used_region(struct mem_region_root *r,
struct mem_region *m)
{
@@ -124,6 +150,11 @@ stat_t init_region(struct mem_region_root *r, vm_t start, size_t arena_size)
return OK;
}
+/**
+ * Destroy memory region and all its children.
+ *
+ * @param n \ref sp_node of memory region to destroy.
+ */
static void __destroy_region(struct sp_node *n)
{
if (!n)
@@ -169,6 +200,15 @@ struct mem_region *find_used_region(struct mem_region_root *r, vm_t start)
return 0;
}
+/**
+ * Create memory region.
+ *
+ * @param start Start of region.
+ * @param end End of region.
+ * @param prev Previous region.
+ * @param next Next region.
+ * @return Created region.
+ */
static struct mem_region *__create_region(vm_t start, vm_t end,
struct mem_region *prev,
struct mem_region *next)
@@ -181,8 +221,12 @@ static struct mem_region *__create_region(vm_t start, vm_t end,
return m;
}
-/** \todo should probably check if this actually works :D seems to do, but that's
- * just from really quick checking */
+/**
+ * Get first order size smaller than \c s in bytes.
+ *
+ * @param s Size to look for.
+ * @return Size of first order smaller than \c s.
+ */
static size_t po_align(size_t s)
{
for (size_t o = __mm_max_order; o > 0; --o) {
@@ -270,6 +314,17 @@ struct mem_region *find_first_region(struct mem_region_root *r)
return m;
}
+/**
+ * Carve out new used memory region from free memory region.
+ *
+ * @param r Memory region root to work in.
+ * @param m Free memory region to carve used memory region out of.
+ * @param pages Number of base order pages to give used region.
+ * @param align Alignment of used region. In this case, start of used region
+ * from start of free region.
+ * @param flags Flags of used region.
+ * @return Start address of used region.
+ */
static vm_t __partition_region(struct mem_region_root *r, struct mem_region *m,
size_t pages, size_t align, vmflags_t flags)
{
@@ -368,6 +423,12 @@ vm_t alloc_fixed_region(struct mem_region_root *r, vm_t start, size_t size,
return __partition_region(r, m, pages, start - m->start, flags);
}
+/**
+ * Try to coalesce two adjacent memory regions, iterating left.
+ *
+ * @param r Memory region root to work in.
+ * @param m Memory region to start trying to coalesce.
+ */
static void __try_coalesce_prev(struct mem_region_root *r, struct mem_region *m)
{
while (m) {
@@ -391,6 +452,12 @@ static void __try_coalesce_prev(struct mem_region_root *r, struct mem_region *m)
}
}
+/**
+ * Try to coalesce two adjacent memory region, iterating right.
+ *
+ * @param r Memory region root to work in.
+ * @param m Memory region to start trying to coalesce.
+ */
static void __try_coalesce_next(struct mem_region_root *r, struct mem_region *m)
{
while (m) {
@@ -414,6 +481,12 @@ static void __try_coalesce_next(struct mem_region_root *r, struct mem_region *m)
}
}
+/**
+ * Try coalescing memory regions.
+ *
+ * @param r Memory region root to work in.
+ * @param m Memory region to start trying to coalesce.
+ */
static void __try_coalesce_regions(struct mem_region_root *r,
struct mem_region *m)
{
diff --git a/common/nodes.c b/common/nodes.c
index ce33547..9cfd2a2 100644
--- a/common/nodes.c
+++ b/common/nodes.c
@@ -41,9 +41,20 @@
* being free)
*/
+/**
+ * Get start of node region from pointer.
+ *
+ * @param r Pointer to node inside node region.
+ * @return Corresponding node region.
+ */
#define node_region(r) \
((struct node_region *)((uintptr_t)(r) & ~(BASE_PAGE_SIZE - 1)))
+/**
+ * Create new node region.
+ *
+ * @return Pointer to created region.
+ */
static struct node_region *__create_region()
{
struct node_region *r = (struct node_region *)alloc_page(BASE_PAGE, 0);
@@ -78,6 +89,13 @@ void destroy_nodes(struct node_root *r)
}
}
+/**
+ * Find free node in node region.
+ *
+ * @param r Node root to work in.
+ * @param nr Node region to look in.
+ * @return Pointer to free node.
+ */
static void *__find_free_node(struct node_root *r, struct node_region *nr)
{
uint8_t *bitmap = r->bitmap + (uint8_t *)nr;
@@ -92,6 +110,11 @@ static void *__find_free_node(struct node_root *r, struct node_region *nr)
return 0;
}
+/**
+ * Pop free list head.
+ *
+ * @param r Node region root to work in.
+ */
static void __pop_av_head(struct node_root *r)
{
struct node_region *t = r->av_head;
@@ -124,6 +147,12 @@ void *get_node(struct node_root *r)
return p;
}
+/**
+ * Push free list head.
+ *
+ * @param r Node region root to work in.
+ * @param nr Node region to push.
+ */
static void __push_av_head(struct node_root *r, struct node_region *nr)
{
nr->av_prev = 0;
@@ -134,6 +163,12 @@ static void __push_av_head(struct node_root *r, struct node_region *nr)
r->av_head = nr;
}
+/**
+ * Free a node region.
+ *
+ * @param r Node region root to work in.
+ * @param nr Node region to free.
+ */
static void __free_region(struct node_root *r, struct node_region *nr)
{
struct node_region *av_n = nr->av_next;
diff --git a/common/tcb.c b/common/tcb.c
index c8260ff..119898f 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -19,13 +19,21 @@
#include <arch/vmem.h>
/* arguably exessively many globals... */
+/** Thread ID to start looking from when allocating new ID. */
static id_t start_tid;
+
+/** Total number of possible thread IDs. */
static size_t num_tids;
+/** Pointer to array of \ref tcb structures. Length of the array is \c num_tids.*/
static struct tcb **tcbs;
-/* if we ever support systems with massive amounts of cpus, this should probably
- * be allocated at runtime */
+/**
+ * Array of thread control block associated with each cpu.
+ *
+ * \todo If we ever support systems with massive amounts of cpus, this should probably
+ * be allocated at runtime.
+ */
static struct tcb *cpu_tcb[MAX_CPUS] = { 0 };
void init_tcbs()
@@ -43,6 +51,12 @@ void destroy_tcbs()
free_page(MM_O1, (pm_t)tcbs);
}
+/**
+ * Allocate a new thread ID.
+ *
+ * @param t Thread to allocate new ID to.
+ * @return Allocated ID.
+ */
static id_t __alloc_tid(struct tcb *t)
{
/** \todo this would need some locking or something... */
@@ -58,7 +72,17 @@ static id_t __alloc_tid(struct tcb *t)
return ERR_NF;
}
-/** \todo add error checking */
+/**
+ * Setup RPC stack.
+ *
+ * RPC stack is local to each thread, and should not be visible to other threads
+ * in the same process.
+ *
+ * @param t Thread to setup RPC stack for.
+ * @param bytes Minimum size of RPC stack.
+ * @return Base of allocated RPC stack.
+ *
+ * \todo add error checking */
static vm_t __setup_rpc_stack(struct tcb *t, size_t bytes)
{
pm_t offset = 0;
@@ -74,6 +98,13 @@ static vm_t __setup_rpc_stack(struct tcb *t, size_t bytes)
return RPC_STACK_TOP - BASE_PAGE_SIZE * pages;
}
+/**
+ * Setup thread stack.
+ *
+ * @param t Thread to setup stack for.
+ * @param bytes Minimum size of stack.
+ * @return Base of allocated stack.
+ */
static vm_t __setup_thread_stack(struct tcb *t, size_t bytes)
{
return alloc_uvmem(t, bytes, VM_V | VM_R | VM_W | VM_U);
@@ -132,6 +163,13 @@ struct tcb *create_thread(struct tcb *p)
return t;
}
+/**
+ * Copy process, setting up COW.
+ *
+ * @param p Parent process.
+ * @param n New process.
+ * @return \ref OK.
+ */
static stat_t __copy_proc(struct tcb *p, struct tcb *n)
{
/** \todo Copy memory regions, and mark them MR_COW, as well as copy
@@ -155,6 +193,12 @@ struct tcb *create_proc(struct tcb *p)
return n;
}
+/**
+ * Destroy data associated with thread.
+ *
+ * @param t Thread whose data to destroy.
+ * @return \ref OK.
+ */
static stat_t __destroy_thread_data(struct tcb *t)
{
/* free rpc vmem */
@@ -195,6 +239,13 @@ stat_t destroy_proc(struct tcb *p)
return __destroy_thread_data(p);
}
+/**
+ * Convenience marco for defining function to attach a thread to either process
+ * or RPC context.
+ *
+ * @param name name of function to define.
+ * @param type Field name of type \c tcb_ctx.
+ */
#define DEFINE_ATTACH(name, type) \
stat_t name(struct tcb *r, struct tcb *t) \
{ \
@@ -212,6 +263,13 @@ stat_t destroy_proc(struct tcb *p)
DEFINE_ATTACH(attach_rpc, rpc);
DEFINE_ATTACH(attach_proc, proc);
+/**
+ * Convenience marco for defining function to detach a thread from either process
+ * or RPC context.
+ *
+ * @param name name of function to define.
+ * @param type Field name of type \c tcb_ctx.
+ */
#define DEFINE_DETACH(name, type) \
stat_t name(struct tcb *r, struct tcb *t) \
{ \
diff --git a/common/timer.c b/common/timer.c
index aaaf62e..6dc1bce 100644
--- a/common/timer.c
+++ b/common/timer.c
@@ -24,19 +24,45 @@
#include <arch/timer.h>
#include <arch/cpu.h>
+/** Timer resolution. */
static ticks_t ticks_per_sec = 0;
+
+/** Array of timer maps for each cpu. */
static struct sp_root cpu_timers[MAX_CPUS] = { 0 };
+
+/** Timer node subsystem instance. */
static struct node_root node_root;
+/** Node in timer map. */
struct timer_node {
+ /** Sp tree node. */
struct sp_node sp_n;
+
+ /** Corresponding timer. */
struct timer timer;
};
+/**
+ * Get \ref timer_node from \ref sp_node.
+ *
+ * @param ptr \ref sp_node whose parent \ref timer_node to get.
+ * @return Corresponding \ref timer_node.
+ */
#define timer_container(ptr) container_of(ptr, struct timer_node, sp_n)
+/**
+ * Get \ref timer_node from \ref timer.
+ *
+ * @param ptr \ref timer whose parent \ref timer_node to get.
+ * @return Corresponding \ref timer_node.
+ */
#define timer_node_container(ptr) container_of(ptr, struct timer_node, timer)
+/**
+ * Get timer map of current cpu.
+ *
+ * @return Root of current cpu's timer map.
+ */
static struct sp_root *__cpu_timers()
{
return &cpu_timers[cpu_id()];
@@ -50,6 +76,15 @@ void init_timer(const void *fdt)
init_nodes(&node_root, sizeof(struct timer_node));
}
+/**
+ * Insert timer into current cpu's timer map.
+ *
+ * \note \c ti.cid might change during the insertion if there already is a node
+ * with identical \c cid to avoid collisions. Very unlikely though.
+ *
+ * @param ti Timer node to insert.
+ * @return \c cid of timer node.
+ */
static id_t __insert_timer(struct timer_node *ti)
{
struct sp_root *root = __cpu_timers();
@@ -88,7 +123,13 @@ static id_t __insert_timer(struct timer_node *ti)
return ti->timer.cid;
}
-/* ticks is absolute */
+/**
+ * Create timer at absolute timepoint.
+ *
+ * @param tid Requesting thread ID.
+ * @param ticks Absolute timepoint.
+ * @return \c cid of created timer.
+ */
static id_t __new_timer(id_t tid, ticks_t ticks)
{
struct timer_node *ti = (struct timer_node *)get_node(&node_root);
diff --git a/common/uapi/conf.c b/common/uapi/conf.c
index 47a7a0f..470b81e 100644
--- a/common/uapi/conf.c
+++ b/common/uapi/conf.c
@@ -15,11 +15,28 @@
size_t __thread_stack_size = SZ_2M;
size_t __call_stack_size = SZ_2M;
+/**
+ * Configuration parameter read syscall handler.
+ *
+ * \todo Implement parameters.
+ *
+ * @param param Parameter to read.
+ * @return \ref OK and parameter value.
+ */
SYSCALL_DEFINE1(conf_get)(sys_arg_t param)
{
return (struct sys_ret){ OK, 0 };
}
+/**
+ * Configuration parameter write syscall handler.
+ *
+ * \todo Implement parameters.
+ *
+ * @param param Parameter to write.
+ * @param val Value to set \c param to.
+ * @return \ref OK and \c 0.
+ */
SYSCALL_DEFINE2(conf_set)(sys_arg_t param, sys_arg_t val)
{
UNUSED(param);
@@ -29,6 +46,13 @@ SYSCALL_DEFINE2(conf_set)(sys_arg_t param, sys_arg_t val)
return (struct sys_ret){ OK, 0 };
}
+/**
+ * Poweroff syscall handler.
+ *
+ * @param type Type of poweroff.
+ * @return \ref ERR_INVAL and \c 0 if incorrect poweroff \c type give, otherwise
+ * does not return.
+ */
SYSCALL_DEFINE1(poweroff)(sys_arg_t type)
{
switch (type) {
diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c
index 52cf8d9..c2ddbcf 100644
--- a/common/uapi/dispatch.c
+++ b/common/uapi/dispatch.c
@@ -9,6 +9,7 @@
#include <apos/debug.h>
#include <apos/uapi.h>
+/** Syscall number to syscall handler conversion. */
static const sys_t syscall_table[] = {
/* noop */
[SYS_NOOP] = sys_noop,
@@ -43,6 +44,11 @@ static const sys_t syscall_table[] = {
[SYS_POWEROFF] = sys_poweroff,
};
+/**
+ * Noop syscall handler.
+ *
+ * @return \ref OK and \c 0.
+ */
SYSCALL_DEFINE0(noop)(){
info("sys_noop\n");
return (struct sys_ret){ OK, 0 };
diff --git a/common/uapi/ipc.c b/common/uapi/ipc.c
index 8584673..4cdec0c 100644
--- a/common/uapi/ipc.c
+++ b/common/uapi/ipc.c
@@ -9,6 +9,13 @@
#include <apos/uapi.h>
#include <apos/tcb.h>
+/**
+ * IPC server notification syscall handler.
+ *
+ * @param callback Address of server callback.
+ * @return \ref ERR_EXT and \c 0 if process already is a server,
+ * \ref OK and \c 0 otherwise.
+ */
SYSCALL_DEFINE1(ipc_server)(sys_arg_t callback)
{
struct tcb *r = cur_tcb();
@@ -19,6 +26,14 @@ SYSCALL_DEFINE1(ipc_server)(sys_arg_t callback)
return (struct sys_ret){ OK, 0 };
}
+/**
+ * IPC request syscall handler.
+ *
+ * @param pid Process to request RPC to.
+ * @param d0 IPC argument 0.
+ * @param d1 IPC argument 1.
+ * @return \c d0 and \c d1.
+ */
SYSCALL_DEFINE3(ipc_req)(sys_arg_t pid, sys_arg_t d0, sys_arg_t d1)
{
struct tcb *r = get_tcb(pid);
@@ -27,13 +42,28 @@ SYSCALL_DEFINE3(ipc_req)(sys_arg_t pid, sys_arg_t d0, sys_arg_t d1)
return (struct sys_ret){ d0, d1 };
}
-SYSCALL_DEFINE3(ipc_fwd)(sys_arg_t tid, sys_arg_t d0, sys_arg_t d1)
+/**
+ * IPC forwarding syscall handler.
+ *
+ * @param pid Process to rquest RPC to.
+ * @param d0 IPC argument 0.
+ * @param d1 IPC argument 1.
+ * @return \c d0 and \c d1.
+ */
+SYSCALL_DEFINE3(ipc_fwd)(sys_arg_t pid, sys_arg_t d0, sys_arg_t d1)
{
- struct tcb *t = get_tcb(tid);
+ struct tcb *t = get_tcb(pid);
/* ditto */
return (struct sys_ret){ d0, d1 };
}
+/**
+ * IPC response syscall handler.
+ *
+ * @param d0 IPC return value 0.
+ * @param d1 IPC return value 1.
+ * @return \c d0 and \c d1.
+ */
SYSCALL_DEFINE2(ipc_resp)(sys_arg_t d0, sys_arg_t d1)
{
struct tcb *r = cur_tcb();
diff --git a/common/uapi/mem.c b/common/uapi/mem.c
index 374e722..71686d6 100644
--- a/common/uapi/mem.c
+++ b/common/uapi/mem.c
@@ -4,6 +4,7 @@
/**
* @file mem.c
* Memory handling syscall implementations.
+ * \todo Should we return more error information?
*/
#include <apos/uapi.h>
@@ -11,33 +12,76 @@
#include <apos/vmem.h>
#include <apos/dmem.h>
+/**
+ * Memory request syscall handler.
+ *
+ * @param size Minimum size of allocation.
+ * @param flags Flags of allocation.
+ * @return \ref OK and start of allocation when succesful,
+ * \ref ERR_OOMEM and \c NULL otherwise.
+ */
SYSCALL_DEFINE2(req_mem)(sys_arg_t size, sys_arg_t flags)
{
/* get current effective process */
struct tcb *r = cur_proc();
- return (struct sys_ret){ OK, alloc_uvmem(r, size, flags) };
+ vm_t start = 0;
+ if ((start = alloc_uvmem(r, size, flags)))
+ return (struct sys_ret){ ERR_OOMEM, NULL };
+
+ return (struct sys_ret){ OK, start };
}
+/**
+ * Fixed memory request syscall handler.
+ *
+ * @param start Address which should be included in allocation.
+ * @param size Minimum size of allocation after \c start.
+ * @param flags Flags of allocation.
+ * @return \ref OK and start of allocation when succesful,
+ * \ref ERR_OOMEM and \c NULL otherwise.
+ */
SYSCALL_DEFINE3(req_fixmem)(sys_arg_t start, sys_arg_t size, sys_arg_t flags)
{
struct tcb *r = cur_proc();
- /* should probably check if the allocation succeeded...? \todo */
- return (struct sys_ret){ OK, alloc_fixed_uvmem(r, start, size, flags) };
+ vm_t start = 0;
+ if ((start = alloc_fixed_uvmem(r, start, size, flags)))
+ return (sys_ret){ ERR_OOMEM, NULL };
+
+ return (struct sys_ret){ OK, start };
}
+/**
+ * Free memory syscall handler.
+ *
+ * @param start Start of allocation to free.
+ * @return \ref OK and \c 0 when succesful, \ref ERR_NF and \c 0 otherwise.
+ */
SYSCALL_DEFINE1(free_mem)(sys_arg_t start)
{
struct tcb *r = cur_proc();
vm_t vm_start = (vm_t)start;
+ stat_t status = OK;
if (vm_start > __pre_top && vm_start < __post_base)
- free_uvmem(r, vm_start);
+ status = free_uvmem(r, vm_start);
else
- free_devmem(r, vm_start);
+ status = free_devmem(r, vm_start);
+
+ if (status)
+ return (struct sys_ret){ ERR_NF, 0 };
return (struct sys_ret){ OK, 0 };
}
+/**
+ * Request physical memory syscall handler.
+ *
+ * @param paddr Physical address to map.
+ * @param size Minimum size of allocation.
+ * @param flags Flags of allocation.
+ * @return \ref OK and start of allocation when succesful,
+ * \ref ERR_OOMEM and \c NULL otherwise.
+ */
SYSCALL_DEFINE3(req_pmem)(sys_arg_t paddr, sys_arg_t size, sys_arg_t flags)
{
/* this will require some pondering, but essentially this syscall should
@@ -46,29 +90,48 @@ SYSCALL_DEFINE3(req_pmem)(sys_arg_t paddr, sys_arg_t size, sys_arg_t flags)
* that keeps track of used regions outside of RAM. We'll see.
*/
struct tcb *r = cur_proc();
- return (struct sys_ret){ OK, alloc_devmem(r, paddr, size, flags) };
+ vm_t start = 0;
+ if ((start = alloc_devmem(r, paddr, size, flags)))
+ return (struct sys_ret){ ERR_OOMEM, NULL };
+
+ return (struct sys_ret){ OK, start };
}
+/**
+ * Request shared memory syscall handler.
+ *
+ * @param size Minimum size of allocation.
+ * @param flags Flags of allocation.
+ * @return \ref OK and start of allocation when succesful,
+ * \ref ERR_OOMEM and \c NULL otherwise.
+ */
SYSCALL_DEFINE2(req_sharedmem)(sys_arg_t size, sys_arg_t flags)
{
/** \todo check that requester is server */
struct tcb *t = cur_proc();
vm_t start = 0;
if ((start = alloc_shared_uvmem(t, size, flags)))
- return (struct sys_ret){ ERR_OOMEM, 0 };
+ return (struct sys_ret){ ERR_OOMEM, NULL };
return (struct sys_ret){ OK, start };
}
-/* add a syscall like ref_sharedmem that adds a reference to an existing shared
- * memory region to a new tid? */
+/**
+ * Reference shared memory syscall handler.
+ *
+ * @param tid Thread ID of shared memory owner.
+ * @param va Start of shared memory in \c tid.
+ * @param flags Flags of reference.
+ * @return \ref OK and start of reference when succesful,
+ * \ref ERR_OOMEM and \c NULL otherwise.
+ */
SYSCALL_DEFINE3(ref_sharedmem)(sys_arg_t tid, sys_arg_t va, sys_arg_t flags)
{
struct tcb *t1 = cur_tcb();
struct tcb *t2 = get_tcb(tid);
vm_t start = 0;
if ((start = ref_shared_uvmem(t1, t2, va, flags)))
- return (struct sys_ret){ ERR_OOMEM, 0 };
+ return (struct sys_ret){ ERR_OOMEM, NULL };
return (struct sys_ret){ OK, start };
}
diff --git a/common/uapi/proc.c b/common/uapi/proc.c
index 79d243f..60617b4 100644
--- a/common/uapi/proc.c
+++ b/common/uapi/proc.c
@@ -12,11 +12,21 @@
#include <apos/bits.h>
#include <apos/mem_regions.h>
+/**
+ * Create syscall handler.
+ *
+ * \todo Implement.
+ *
+ * @return \ref OK and 0.
+ */
SYSCALL_DEFINE0(create)(){
return (struct sys_ret){ OK, 0 };
}
-/* Not entirely sure how I should handle forks/execs etc, mostly whether I
+/**
+ * Fork syscall handler.
+ *
+ * \todo Not entirely sure how I should handle forks/execs etc, mostly whether I
* should allow forks/execs to be called directly or only though the process
* manager. Probably though the process manager, although that will add in a
* slight bit of delay.
@@ -25,11 +35,20 @@ SYSCALL_DEFINE0(create)(){
* that would allow them to be called directly, and then the process manager
* would have to periodically ask the kernel about all threads it is aware of
* via sys_sync. Dunno.
+ *
+ * @return \ref OK and 0.
*/
SYSCALL_DEFINE0(fork)(){
return (struct sys_ret){ OK, 0 };
}
+/**
+ * Exec syscall handler.
+ *
+ * @param bin Binary to execute.
+ * @param interp Optional interpreter binary.
+ * @return \see prepare_proc() and 0.
+ */
SYSCALL_DEFINE2(exec)(sys_arg_t bin, sys_arg_t interp){
/** \todo execute new process, probably with more sensible argc passing */
struct tcb *r = cur_tcb();
@@ -60,11 +79,29 @@ SYSCALL_DEFINE2(exec)(sys_arg_t bin, sys_arg_t interp){
return (struct sys_ret){ prepare_proc(r, bin, interp), 0 };
}
+/**
+ * Signal syscall handler.
+ *
+ * \todo Implement.
+ *
+ * @param tid Thread ID to signal.
+ * @param signal Signal to send to \c tid.
+ * @return \ref OK and 0.
+ */
SYSCALL_DEFINE2(signal)(sys_arg_t tid, sys_arg_t signal){
- /** \todo signals? */
return (struct sys_ret){ OK, 0 };
}
+/**
+ * Swap syscall handler.
+ *
+ * \todo Implement.
+ * \todo Should swap return the registers of the new thread that would be used
+ * for message passing?
+ *
+ * @param tid Thread ID to swap to.
+ * @return \ref OK and 0.
+ */
SYSCALL_DEFINE1(swap)(sys_arg_t tid){
/** \todo switch to process */
/** \todo should switch return the registers of the new thread that would
diff --git a/common/uapi/timers.c b/common/uapi/timers.c
index bc3ef59..b6f9b95 100644
--- a/common/uapi/timers.c
+++ b/common/uapi/timers.c
@@ -9,39 +9,81 @@
#include <apos/timer.h>
#include <apos/uapi.h>
-static ticks_t scaled_ticks(sys_arg_t ticks, sys_arg_t repeat)
+/**
+ * Convert arch-specific register values \c ticks and \c repeat to \c ticks_t.
+ *
+ * If we're on a 32bit system, one register can't contain a tick value,
+ * so we use two registers and combine them into one value and let the compiler
+ * handle the rest.
+ *
+ * @param ticks Register width tick value.
+ * @param mult Register width repeat value.
+ * @return Corresponding \c ticks_t value.
+ */
+static ticks_t scaled_ticks(sys_arg_t ticks, sys_arg_t mult)
{
-#if __WORDSIZE == 64
- UNUSED(repeat);
+#if defined(_LP64)
+ UNUSED(mult);
return ticks;
#else
- return ((ticks_t)ticks << 32) + repeat;
+ return (ticks_t)ticks * (ticks_t)mult;
#endif
}
+/**
+ * Timebase syscall handler.
+ *
+ * @return \ref OK and resolution of system timer in Hz.
+ */
SYSCALL_DEFINE0(timebase)()
{
return (struct sys_ret){ OK, secs_to_ticks(1) };
}
-SYSCALL_DEFINE2(req_rel_timer)(sys_arg_t ticks, sys_arg_t repeat)
+/**
+ * Relative timer request syscall handler.
+ *
+ * \note On 64bit systems, \c repeat is ignored as \c ticks register is large
+ * enough to contain essentially any timepoint we want. A couple thousand years
+ * when the clock runs at 5GHz, if I'm not completely mistaken.
+ *
+ * @param ticks Number of ticks from now.
+ * @param mult Multiply \c ticks by this value.
+ * @return \ref OK and \c cid of created timer.
+ */
+SYSCALL_DEFINE2(req_rel_timer)(sys_arg_t ticks, sys_arg_t mult)
{
return (struct sys_ret){
OK,
new_rel_timer(cur_tcb()->tid,
- scaled_ticks(ticks, repeat))
+ scaled_ticks(ticks, mult))
};
}
-SYSCALL_DEFINE2(req_abs_timer)(sys_arg_t ticks, sys_arg_t repeat)
+/**
+ * Absolute timer request syscall handler.
+ *
+ * @param ticks Absolute timepoint relative to some start point defined at boot.
+ * @param mult Multiply \c ticks by this value.
+ * @return \ref OK and \c cid of created timer.
+ * \see req_rel_timer().
+ */
+SYSCALL_DEFINE2(req_abs_timer)(sys_arg_t ticks, sys_arg_t mult)
{
return (struct sys_ret){
OK,
new_abs_timer(cur_tcb()->tid,
- scaled_ticks(ticks, repeat))
+ scaled_ticks(ticks, mult))
};
}
+/**
+ * Free timer request syscall handler.
+ *
+ * @param cid \c cid of timer to free.
+ * @return \ref ERR_NF and \c 0if no timer could be found with \c cid, \ref OK
+ * and 0 otherwise.
+ */
SYSCALL_DEFINE1(free_timer)(sys_arg_t cid)
{
struct timer *timer = find_timer(cid);
diff --git a/common/vmem.c b/common/vmem.c
index eb88552..fe0178e 100644
--- a/common/vmem.c
+++ b/common/vmem.c
@@ -18,6 +18,14 @@ stat_t init_uvmem(struct tcb *t, vm_t base, vm_t top)
return init_region(&t->sp_r, base, top);
}
+/**
+ * Convenience function for freeing mapped regions.
+ *
+ * @param t Thread to work in.
+ * @param m Memory region to free.
+ * @return \ref INFO_SEFF if other thread in process should be synced, \ref OK
+ * otherwise.
+ */
static stat_t __free_mapped_region(struct tcb *t, struct mem_region *m)
{
stat_t status = OK;
@@ -135,12 +143,12 @@ vm_t ref_shared_uvmem(struct tcb *t1, struct tcb *t2, vm_t va, vmflags_t flags)
return v;
}
-/** \todo assume tcb is root tcb? */
stat_t free_uvmem(struct tcb *r, vm_t va)
{
+ /** \todo assume tcb is root tcb? */
struct mem_region *m = find_used_region(&r->sp_r, va);
if (!m)
- return -1;
+ return ERR_NF;
free_region(&r->sp_r, va);