From e30cd339e271b0d16dbecf6c521fa06c3a05e3f1 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 8 Jun 2022 22:46:55 +0300 Subject: continue documentation --- include/apos/syscalls.h | 100 ++++++++++++++------ include/apos/tcb.h | 238 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 304 insertions(+), 34 deletions(-) diff --git a/include/apos/syscalls.h b/include/apos/syscalls.h index 7e2845b..b0d6423 100644 --- a/include/apos/syscalls.h +++ b/include/apos/syscalls.h @@ -6,45 +6,89 @@ * Table of system calls. */ -/* enum for now, possibly macros in the future once I get an approximate idea of +/** enum for now, possibly macros in the future once I get an approximate idea of * which syscalls are necessary etc. */ enum { - /* noop, for testing out how many syscalls per second can done I suppose - * */ + /** @name Misc. */ + /** @{ */ + /** Noop, mainly for testing syscall subsystem and sanity checking. */ SYS_NOOP, + /** @} */ - /* memory management */ - SYS_REQ_MEM, /* request memory from anywhere */ - SYS_REQ_PMEM, /* request physical address */ - SYS_REQ_FIXMEM, /* request memory at fixed address */ - SYS_FREE_MEM, /* free memory */ + /* @name Memory management. */ + /** @{ */ + /** Request memory from anywhere. */ + SYS_REQ_MEM, - /* timers */ + /** Request memory with physical address. */ + SYS_REQ_PMEM, + + /** Request memory at fixed virtual address. */ + SYS_REQ_FIXMEM, + + /** Free memory. */ + SYS_FREE_MEM, + /** @} */ + + /** @name Timers */ + /** @{ */ + /** Get accuracy of clock in Hertz. */ SYS_TIMEBASE, + + /** Request relative timer (number of ticks from now). */ SYS_REQ_REL_TIMER, + + /** Request absolute timer (timepoint in ticks). */ SYS_REQ_ABS_TIMER, + + /** Remove timer. */ SYS_FREE_TIMER, + /** @} */ + + /** @name IPC. */ + /** @{ */ + /** Inform kernel that process should be treated as server. */ + SYS_IPC_SERVER, - /* IPC */ - /* I really should try to find my notes about the server/client - * structure of the OS, but these following syscalls are probably - * required */ - SYS_IPC_SERVER, /* inform kernel that process should be treated as a server */ + /** Send IPC request as client. */ SYS_IPC_REQ, /* IPC request to server */ - SYS_IPC_FWD, /* IPC request forwarding */ - SYS_IPC_RESP, /* IPC response from server */ - - /* process management */ - SYS_CREATE, /* create new thread */ - SYS_FORK, /* duplicate process */ - SYS_EXEC, /* execute new binary in process space */ - SYS_KILL, /* kill thread */ - SYS_SIGNAL, /* send signal to process (kill etc.) */ - SYS_SWAP, /* switch running process */ - - /* kernel management */ - SYS_CONF, /* config system parameters (stack size etc.) */ - SYS_POWEROFF, /* shutdown/reboot etc. */ + + /** Forward IPC request from client. */ + SYS_IPC_FWD, + + /** IPC response from server. */ + SYS_IPC_RESP, + /** @} */ + + /** @name Process management. */ + /** @{ */ + /** Create new thread. */ + SYS_CREATE, + + /** Duplicate process. */ + SYS_FORK, + + /** Execute new binary in process space. */ + SYS_EXEC, + + /** Kill thread. */ + SYS_KILL, + + /** Send signal to thread. */ + SYS_SIGNAL, + + /** Switch running process. */ + SYS_SWAP, + /** @} */ + + /** @name Kernel management. */ + /** @{ */ + /** Configure system parameters (stack size etc.). */ + SYS_CONF, + + /** Shutdown, reboot, etc. */ + SYS_POWEROFF, + /** @} */ }; /* function declarations should be somewhere else, this file could be used in diff --git a/include/apos/tcb.h b/include/apos/tcb.h index 1a633be..4d4b3d5 100644 --- a/include/apos/tcb.h +++ b/include/apos/tcb.h @@ -10,65 +10,291 @@ #include #include /* arch-specific data */ -/* process(/main) threads don't have any previous threads */ +/** + * Check if thread is process thread. + * + * @param t Thread to check. + * @return \c true if thread is process thread, \c false otherwise. + */ #define is_proc(t) (t->rid == t->tid) + +/** + * Check if thread is in RPC. + * + * @param t Thread to check. + * @return \c true if thread is in RPC, \c false otherwise. + */ #define is_rpc(t) (t->rid == t->pid) +/** + * Get the process thread of current thread. + * + * @param t Thread whose effective process thread to get. + * @return The process thread of the current thread. + */ #define get_proc(t) (get_tcb(t->eid)) + +/** + * Get the root process thread of current thread. + * + * @param t Thread whose root process thread to get. + * @return The root process thread of the current thread. + */ #define get_rproc(t) (get_tcb(t->rid)) /* forward declaration */ struct tcb; +/** Convenience structure for \see tcb. */ struct tcb_ctx { + /** Virtual address space of context. */ struct vmem *vmem; + + /** Next thread in context. */ struct tcb *next; + + /** Previous thread in context. */ struct tcb *prev; }; +/** Thread control block. Main way to handle threads. */ struct tcb { + /** Arch-specific data. */ struct arch_tcbd tcbd; - /* mapping data */ + /** Memory mapping data. */ struct mem_region_root sp_r; + /** + * Effective process ID. + * + * This is the ID on which globally visible stuff should occur, such as + * memory allocations etc. + * + * When a thread is in an RPC, and a \ref SYS_IPC_FWD request occurs, the \c + * eid of the thread remains the same, whereas in a regular \c + * SYS_IPC_REQ the \c eid if replaced with the \ref pid of the + * process the thread is visiting. + */ id_t eid; + + /** + * Actual process ID. + * + * This, along with \ref eid, creates the backbone of the IPC process ID + * handling. + */ id_t pid; + /** + * Root process ID. + * + * ID of the process that spawned the thread, and the process the thread + * should belong to when not in an RPC. + */ id_t rid; + + /** Thread ID. */ id_t tid; + /* TODO: implement cpu_id to hardware cpu ID translation, first in + * riscv. */ + /** Cpu currently executing this thread. */ + id_t cpu_id; + + /** Address of callback function in servers. */ vm_t callback; + /** Address of this thread's stack base. */ vm_t thread_stack; + + /** Address of this thread's stack top. */ vm_t thread_stack_top; + + /* TODO: Check if each thread should be allowed more than just one + * region of thread local storage. */ + /** Possible thread local storage. */ vm_t thread_storage; + /** Process context of thread. */ struct tcb_ctx proc; + + /** RPC context of thread. */ struct tcb_ctx rpc; }; +/** + * Initialize thread control subsystem. + */ void init_tcbs(); + +/** + * Destroy thread control subsystem. + */ void destroy_tcbs(); +/** + * Create a new thread. + * + * If \c p is \c NULL, then a new process context is created for the thread. + * Otherwise, the thread is inserted into \c p. + * + * The thread is allocated a virtual address space, as well as a kernel stack + * and the \ref tcb structure itself with a unique thread ID. If in a new + * process context, a new process address space is created as well. + * + * Userspace stack is allocated with \ref alloc_stacks(). + * + * @todo Thread local storage? + * + * @param p Process context within to create the thread. + * @return Pointer to created \ref tcb. + */ struct tcb *create_thread(struct tcb *p); + +/** + * Create a new process. + * + * Sets up a new thread in a new process context. If there is a parent thread, + * its memory regions are copied but made COW. + * @see create_thread(). + * + * @todo COW handling. + * + * @param p Parent process. + * @return Pointer to created \ref tcb. + */ struct tcb *create_proc(struct tcb *p); + +/** + * Destroy a thread. + * + * Frees data associated with thread and frees up the thread ID. + * At least currently does not allow \c t to be a process thread. + * + * @todo Other return values? + * + * @param t Thread to destroy. + * @return \ref OK on success, \ref ERR_NOINIT if called without initializing + * subsystem and \ref ERR_INVAL if called with a process thread. + */ stat_t destroy_thread(struct tcb *t); + +/** + * Destroy a process. + * + * Frees all data associated with the process and destroys all threads within + * it. + * + * @param p Process to destroy. + * @return \ref OK on success, \ref ERR_NOINIT if called without initializing + * subsystem and \ref ERR_INVAL if called without a process thread. + */ stat_t destroy_proc(struct tcb *p); +/** + * Attach a thread to an RPC context. + * + * Essentially inserts thread \c t into the process \c r, with access to the + * same memory except for the RPC stack. + * + * @param r Process to attach to. + * @param t Thread to attach. + * @return \ref OK on success, \ref ERR_INVAL if pointers are the same. + */ stat_t attach_rpc(struct tcb *r, struct tcb *t); + +/** + * Detach a thread from an RPC context. + * + * \see attach_rpc(). + * + * @param r Process to detach from. + * @param t Thread to detach. + * @return \ref OK on success, \ref ERR_INVAL if pointers are the same. + * + * @todo Should probably check that thread exists in the process? + */ stat_t detach_rpc(struct tcb *r, struct tcb *t); + +/** + * Attach a thread in a process context. + * + * @param r Process to attach to. + * @param t Thread to attach. + * @return \ref OK on success, \ref ERR_INVAL if pointers are the same. + */ stat_t attach_proc(struct tcb *r, struct tcb *t); + +/** + * Detach a thread from a process context. + * + * @param r Process to detach from. + * @param t Thread to detach. + * @return \ref OK on success, \ref ERR_INVAL if pointers are the same. + */ stat_t detach_proc(struct tcb *r, struct tcb *t); +/** + * Get currently executing thread. + * + * @return Current \ref tcb. + */ struct tcb *cur_tcb(); + +/** + * Get currently executing process. + * + * @return Current process \ref tcb. + */ struct tcb *cur_proc(); -void use_tcb(struct tcb *); +/** + * Set \c t as current \ref tcb. + * + * @param t Thread to mark as current. + */ +void use_tcb(struct tcb *t); + +/** + * Get \ref tcb corresponding to thread with ID \c tid. + * + * @param tid Thread ID. + * @return Corresponding \ref tcb or \c NULL if not found. + */ struct tcb *get_tcb(id_t tid); -stat_t clone_proc_maps(struct tcb *); -stat_t clone_rpc_maps(struct tcb *); -stat_t alloc_stacks(struct tcb *); +/** + * Clone process context memory mappings. + * + * Essentially make sure all threads in the process have identical memory + * mappings. + * + * @param p Process whose memory mappings to clone. + * @return \ref OK on success, something else otherwise. + * @todo Check up on return codes. + */ +stat_t clone_proc_maps(struct tcb *p); + +/** + * Clone RPC context memory mappings. + * + * @see clone_proc_maps(). + * + * @param r Server whose memory mappings to clone to threads in RPC to it. + * @return \ref OK on success, something else otherwise. + * @todo Check up on return codes. + */ +stat_t clone_rpc_maps(struct tcb *r); + +/** + * Allocate stacks for thread. + * + * Both user stack and RPC stack. + * + * @param t Thread whose stacks to allocate. + * @return \ref OK on success, \ref ERR_OOMEM if out of memory. + */ +stat_t alloc_stacks(struct tcb *t); #endif /* APOS_TCB_H */ -- cgit v1.3