diff options
author | nthnluu <nate1299@me.com> | 2024-01-28 21:20:27 -0500 |
---|---|---|
committer | nthnluu <nate1299@me.com> | 2024-01-28 21:20:27 -0500 |
commit | c63f340d90800895f007de64b7d2d14624263331 (patch) | |
tree | 2c0849fa597dd6da831c8707b6f2603403778d7b /kernel/include/proc |
Created student weenix repository
Diffstat (limited to 'kernel/include/proc')
-rw-r--r-- | kernel/include/proc/context.h | 62 | ||||
-rw-r--r-- | kernel/include/proc/core.h | 15 | ||||
-rw-r--r-- | kernel/include/proc/kmutex.h | 60 | ||||
-rw-r--r-- | kernel/include/proc/kthread.h | 106 | ||||
-rw-r--r-- | kernel/include/proc/proc.h | 200 | ||||
-rw-r--r-- | kernel/include/proc/sched.h | 126 | ||||
-rw-r--r-- | kernel/include/proc/spinlock.h | 37 |
7 files changed, 606 insertions, 0 deletions
diff --git a/kernel/include/proc/context.h b/kernel/include/proc/context.h new file mode 100644 index 0000000..63c692e --- /dev/null +++ b/kernel/include/proc/context.h @@ -0,0 +1,62 @@ +#pragma once + +#include "types.h" + +#include "mm/pagetable.h" + +/* + * The function pointer to be implemented by functions which are entry + * points for new threads. + */ +typedef void *(*context_func_t)(long, void *); + +typedef struct context +{ + uintptr_t c_rip; /* instruction pointer (RIP) */ + uintptr_t c_rsp; /* stack pointer (RSP) */ + uintptr_t c_rbp; /* frame pointer (RBP) */ + + pml4_t + *c_pml4; /* pointer to the top level page table (PML4) for this proc. + It's the 'root' of the page table where virtual address -> physical address + lookup starts. */ + + uintptr_t c_kstack; + size_t c_kstacksz; +} context_t; + +/** + * Initialize the given context such that when it begins execution it + * will execute func(arg1,arg2). A kernel stack and page directory + * exclusive to this context must also be provided. + * + * @param c the context to initialize + * @param func the function which will begin executing when this + * context is first made active + * @param arg1 the first argument to func + * @param arg2 the second argument to func + * @param kstack a pointer to the kernel stack this context will use + * @param kstacksz the size of the kernel stack + * @param pdptr the pagetable this context will use + */ +void context_setup(context_t *c, context_func_t func, long arg1, void *arg2, + void *kstack, size_t kstacksz, pml4_t *pml4); + +void context_setup_raw(context_t *c, void (*func)(), void *kstack, + size_t kstacksz, pml4_t *pml4); +/** + * Makes the given context the one currently running on the CPU. Use + * this mainly for the initial context. + * + * @param c the context to make active + */ +void context_make_active(context_t *c); + +/** + * Save the current state of the machine into the old context, and begin + * executing the new context. Used primarily by the scheduler. + * + * @param oldc the context to switch from + * @param newc the context to switch to + */ +void context_switch(context_t *oldc, context_t *newc); diff --git a/kernel/include/proc/core.h b/kernel/include/proc/core.h new file mode 100644 index 0000000..9d6eb16 --- /dev/null +++ b/kernel/include/proc/core.h @@ -0,0 +1,15 @@ +#pragma once + +#include "proc/context.h" +#include "proc/sched.h" +#include "proc/spinlock.h" + +typedef struct core +{ + long kc_id; + context_t kc_ctx; + + ktqueue_t *kc_queue; + + uintptr_t kc_csdpaddr; +} core_t; diff --git a/kernel/include/proc/kmutex.h b/kernel/include/proc/kmutex.h new file mode 100644 index 0000000..37d8ece --- /dev/null +++ b/kernel/include/proc/kmutex.h @@ -0,0 +1,60 @@ +#pragma once + +#include "proc/sched.h" +#include "proc/spinlock.h" + +/*=========== + * Structures + *==========*/ + +typedef struct kmutex +{ + ktqueue_t km_waitq; /* wait queue */ + struct kthread *km_holder; /* current holder */ + list_link_t km_link; +} kmutex_t; + +#define KMUTEX_INITIALIZER(mtx) \ + { \ + .km_waitq = KTQUEUE_INITIALIZER((mtx).km_waitq), .km_holder = NULL, \ + .km_link = LIST_LINK_INITIALIZER((mtx).km_link), \ + } + +/*========== + * Functions + *=========*/ + +/** + * Initializes a mutex. + * + * @param mtx the mutex + */ +void kmutex_init(kmutex_t *mtx); + +/** + * Locks the specified mutex. + * + * Note: This function may block. + * + * Note: These locks are not re-entrant + * + * @param mtx the mutex to lock + */ +void kmutex_lock(kmutex_t *mtx); + +/** + * Unlocks the specified mutex. + * + * @param mtx the mutex to unlock + */ +void kmutex_unlock(kmutex_t *mtx); + +/** + * Indicates if a mutex has waiters. + */ +long kmutex_has_waiters(kmutex_t *mtx); + +/** + * Indicates if curthr owns a mutex. + */ +long kmutex_owns_mutex(kmutex_t *mtx); diff --git a/kernel/include/proc/kthread.h b/kernel/include/proc/kthread.h new file mode 100644 index 0000000..6bc66be --- /dev/null +++ b/kernel/include/proc/kthread.h @@ -0,0 +1,106 @@ +#pragma once + +#include <proc/context.h> +#include <proc/sched.h> +#include <proc/spinlock.h> +#include <util/list.h> + +/*===================== + * Types and structures + *====================*/ + +/* + * Alias for an entry point function of a new thread. + */ +typedef context_func_t kthread_func_t; + +/* + * Thread states. + */ +typedef enum +{ + KT_NO_STATE, /* Illegal state */ + KT_ON_CPU, /* Currently running */ + KT_RUNNABLE, /* On the run queue */ + KT_SLEEP, /* Blocked indefinitely */ + KT_SLEEP_CANCELLABLE, /* Blocked, but can be interrupted */ + KT_EXITED /* Exited, waiting to be joined */ +} kthread_state_t; + +/* + * Thread descriptor. + */ +typedef struct kthread +{ + context_t kt_ctx; /* Thread context */ + char *kt_kstack; /* Kernel stack */ + void *kt_retval; /* Return value */ + long kt_errno; /* Errno of most recent syscall */ + struct proc *kt_proc; /* Corresponding process */ + + long kt_cancelled; /* Set if the thread has been cancelled */ + ktqueue_t *kt_wchan; /* If blocking, the queue this thread is blocked on */ + kthread_state_t kt_state; + + list_link_t kt_plink; /* Link on the process's thread list, p_threads */ + list_link_t + kt_qlink; /* Link on some ktqueue if the thread is not running */ + + list_t kt_mutexes; /* List of owned mutexes, for use in debugging */ + long kt_recent_core; /* For SMP */ + + uint64_t kt_preemption_count; +} kthread_t; + +/*========== + * Functions + *=========*/ + +/** + * Initializes the kthread subsystem at system startup. + */ +void kthread_init(void); + +/** + * Allocates and initializes a kernel thread. + * + * @param proc the process in which the thread will run + * @param func the function that will be called when the newly created + * thread starts executing + * @param arg1 the first argument to func + * @param arg2 the second argument to func + * @return the newly created thread + * + */ +kthread_t *kthread_create(struct proc *proc, kthread_func_t func, long arg1, + void *arg2); + +/** + * Creates a clone of the specified thread + * + * @param thr the thread to clone + * @return a clone of thr + */ +kthread_t *kthread_clone(kthread_t *thr); + +/** + * Frees resources associated with a thread. + * + * @param thr the thread to free + */ +void kthread_destroy(kthread_t *thr); + +/** + * Cancels a thread. + * + * @param kthr the thread to be cancelled + * @param retval the return value for the thread + */ +void kthread_cancel(kthread_t *kthr, void *retval); + +/** + * Exits the current thread. + * + * @param retval the return value for the thread + */ +void kthread_exit(void *retval); diff --git a/kernel/include/proc/proc.h b/kernel/include/proc/proc.h new file mode 100644 index 0000000..bc608a0 --- /dev/null +++ b/kernel/include/proc/proc.h @@ -0,0 +1,200 @@ +#pragma once + +#include "config.h" +#include "mm/pagetable.h" +#include "proc/kthread.h" +#include "types.h" +#include "vm/vmmap.h" + +/*=========== + * Structures + *==========*/ + +/* + * Process resource information + */ +#define PROC_MAX_COUNT 65536 +#define PROC_NAME_LEN 256 + +/* Process states */ +typedef enum +{ + PROC_RUNNING, /* Has running threads */ + PROC_DEAD /* Exited, but not yet wait'ed */ +} proc_state_t; + +/* Process descriptor */ +typedef struct proc +{ + pid_t p_pid; /* Process ID */ + char p_name[PROC_NAME_LEN]; /* Process name */ + + list_t p_threads; /* Threads list */ + list_t p_children; /* Children list */ + struct proc *p_pproc; /* Parent process */ + + list_link_t p_list_link; /* Link of list of all processes */ + list_link_t p_child_link; /* Link on parent's list of children */ + + long p_status; /* Exit status */ + proc_state_t p_state; /* Process state */ + + pml4_t *p_pml4; /* Page table. */ + + /* + * If a parent is waiting on a child, the parent puts itself on its own + * p_wait queue. When a child terminates, it broadcasts on its parent's + * p_wait to wake it up. + */ + ktqueue_t p_wait; + + /* VFS related */ + struct file *p_files[NFILES]; /* Open files */ + struct vnode *p_cwd; /* Current working directory */ + + /* VM related */ + /* + * The current value of a process's break is maintained in the 'p_brk'. + * + * The 'p_brk' and 'p_start_brk' members of a proc_t struct are initialized + * by the loader. 'p_start_brk' is subsequently never modified; it always + * holds the initial value of the break. + * + * The loader sets 'p_start_brk' to be the end of the bss section (search + * online for memory layout diagrams of a running process for more + * details). + * + * These are both addresses. + */ + void *p_brk; /* Process break; see brk(2) */ + void *p_start_brk; /* Initial value of process break */ + struct vmmap *p_vmmap; /* List of areas mapped into process's + user address space. */ +} proc_t; + +/*========== + * Functions + *=========*/ + +/** + * Initializes the proc subsystem at system startup. + */ +void proc_init(void); + +/** + * Initializes the special idleproc at system startup. + */ +void proc_idleproc_init(); + +/** + * Shuts down certain subsystems at system shutdown. + */ +void initproc_finish(); + +/** + * Allocates and initializes a new process. + * + * @param name the name to give the newly created process + * @return the newly created process + */ +proc_t *proc_create(const char *name); + +/** + * Frees all the resources associated with a process. + * + * @param proc process to destroy + */ +void proc_destroy(proc_t *proc); + +/** + * Handles exiting the current process. + * + * @param retval exit code for the thread and process + */ +void proc_thread_exiting(void *retval); + +/** + * Stops another process from running again by cancelling all its + * threads. + * + * @param proc the process to kill + * @param status the status the process should exit with + */ +void proc_kill(proc_t *proc, long status); + +/** + * Kills every process except for the idle process and direct children + * of the idle process. + */ +void proc_kill_all(void); + +/*======================== + * Functions: System calls + *=======================*/ + +/** + * Implements the _exit(2) system call. + * + * @param status the exit status of the process + */ +void do_exit(long status); + +/** + * Implements the waitpid(2) system call. + * + * @param pid the pid to wait on, or -1 to wait on any child + * @param status used to return the exit status of the child + * @param options only 0 is supported (no options) + * + * @return the pid of the child process which was cleaned up, or + * - ENOTSUP invalid input + * - ECHILD valid child could not be found + */ +pid_t do_waitpid(pid_t pid, int *status, int options); + +/** + * This function implements the fork(2) system call. + * + * @param regs the register state at the time of the system call + */ +struct regs; +long do_fork(struct regs *regs); + +/*=========== + * Miscellany + *==========*/ + +/* + * Special PIDs reserved for specific processes + */ +#define PID_IDLE 0 +#define PID_INIT 1 + +/* + * Enable global use of idleproc + */ +extern proc_t idleproc; + +/*===================== + * Functions: Debugging + *====================*/ + +/** + * Provides detailed debug information about a given process. + * + * @param arg a pointer to the process + * @param buf buffer to write to + * @param osize size of the buffer + * @return the remaining size of the buffer + */ +size_t proc_info(const void *arg, char *buf, size_t osize); + +/** + * Provides debug information overview of all processes. + * + * @param arg must be NULL + * @param buf buffer to write to + * @param osize size of the buffer + * @return the remaining size of the buffer + */ +size_t proc_list_info(const void *arg, char *buf, size_t osize);
\ No newline at end of file diff --git a/kernel/include/proc/sched.h b/kernel/include/proc/sched.h new file mode 100644 index 0000000..343e8d5 --- /dev/null +++ b/kernel/include/proc/sched.h @@ -0,0 +1,126 @@ +#pragma once + +#include "proc/spinlock.h" +#include "util/list.h" + +/*=========== + * Structures + *==========*/ + +/* + * Queue structure for kthreads + * Note that ktqueue functions are private - managing the queue + * should be done within sched.c, or using public functions + */ +typedef struct ktqueue +{ + list_t tq_list; + size_t tq_size; +} ktqueue_t; + +/* + * Macro to initialize a ktqueue. See sched_queue_init for how the + * queue should be initialized in your code. + */ +#define KTQUEUE_INITIALIZER(ktqueue) \ + { \ + .tq_list = LIST_INITIALIZER((ktqueue).tq_list), \ + } + +/* + * kthread declaration to make function signatures happy + */ +struct kthread; + +/*========== + * Functions + *=========*/ + +/** + * Runs a new thread from the run queue. + * + * @param queue the queue to place curthr on + */ +void sched_switch(ktqueue_t *queue); + +/** + * Helps with context switching. + */ +void core_switch(); + +/** + * Yields the CPU to another runnable thread. + */ +void sched_yield(); + +/** + * Enables a thread to be selected by the scheduler to run. + * + * @param thr the thread to make runnable + */ +void sched_make_runnable(struct kthread *thr); + +/** + * Causes the current thread to enter into an uncancellable sleep on + * the given queue. + * + * @param q the queue to sleep on + * @param lock optional lock for release in another context + */ +void sched_sleep_on(ktqueue_t *q); + +/** + * Causes the current thread to enter into a cancellable sleep on the + * given queue. + * + * @param queue the queue to sleep on + * @param lock optional lock for release in another context + * @return -EINTR if the thread was cancelled and 0 otherwise + */ +long sched_cancellable_sleep_on(ktqueue_t *queue); + +/** + * Wakes up a thread from q. + * + * @param q queue + * @param thrp if an address is provided, *thrp is set to the woken up thread + * + */ +void sched_wakeup_on(ktqueue_t *q, struct kthread **thrp); + +/** + * Wake up all threads running on the queue. + * + * @param q the queue to wake up threads from + */ +void sched_broadcast_on(ktqueue_t *q); + +/** + * Cancel the given thread from the queue it sleeps on. + * + * @param the thread to cancel sleep from + */ +void sched_cancel(struct kthread *thr); + +/** + * Initializes a queue. + * + * @param queue the queue + */ +void sched_queue_init(ktqueue_t *queue); + +/** + * Returns true if the queue is empty. + * + * @param queue the queue + * @return true if the queue is empty + */ +long sched_queue_empty(ktqueue_t *queue); + +/** + * Functions for managing the current thread's preemption status. + */ +void preemption_disable(); +void preemption_enable(); +void preemption_reset(); +long preemption_enabled();
\ No newline at end of file diff --git a/kernel/include/proc/spinlock.h b/kernel/include/proc/spinlock.h new file mode 100644 index 0000000..4ce57c8 --- /dev/null +++ b/kernel/include/proc/spinlock.h @@ -0,0 +1,37 @@ +#pragma once + +typedef struct spinlock +{ + volatile char s_locked; +} spinlock_t; + +#define SPINLOCK_INITIALIZER(lock) \ + { \ + .s_locked = 0 \ + } + +/** + * Initializes the fields of the specified spinlock_t + * @param lock the spinlock to initialize + */ +void spinlock_init(spinlock_t *lock); + +/** + * Locks the specified spinlock. + * + * Note: this function may spin on the current core. + * + * Note: these locks are not re-entrant + * + * @param lock the spinlock to lock + */ +void spinlock_lock(spinlock_t *lock); + +/** + * Unlocks the specified spinlock. + * + * @param lock the spinlock to unlock + */ +void spinlock_unlock(spinlock_t *lock); + +long spinlock_ownslock(spinlock_t *lock); |