diff options
| author | Tianhao Wang <shrik3@mailbox.org> | 2024-06-06 02:08:21 +0200 |
|---|---|---|
| committer | Tianhao Wang <shrik3@mailbox.org> | 2024-06-11 15:17:14 +0200 |
| commit | d495a1745c83a8186bf1c6c531177887dd245436 (patch) | |
| tree | 5ea93adceea22d7aa12eb0165fce80e458dd3864 | |
| parent | a86f59b32eb86a1ccb94bf1e627c1115c3b6b217 (diff) | |
proc: basic infra for multithreading
including task and scheduler wrapper, context swap assembly, and some
notes... The lifetime of task is tricky, I'll fix it later
Signed-off-by: Tianhao Wang <shrik3@mailbox.org>
| -rw-r--r-- | src/arch/x86_64/asm/proc.s | 35 | ||||
| -rw-r--r-- | src/arch/x86_64/asm/toc.s | 0 | ||||
| -rw-r--r-- | src/defs.rs | 5 | ||||
| -rw-r--r-- | src/proc/mod.rs | 1 | ||||
| -rw-r--r-- | src/proc/sched.rs | 17 | ||||
| -rw-r--r-- | src/proc/task.rs | 45 |
6 files changed, 102 insertions, 1 deletions
diff --git a/src/arch/x86_64/asm/proc.s b/src/arch/x86_64/asm/proc.s new file mode 100644 index 0000000..e1996a7 --- /dev/null +++ b/src/arch/x86_64/asm/proc.s @@ -0,0 +1,35 @@ +; vi: ft=nasm +; vectors.s - idt for x86_64 +[BITS 64] +[GLOBAL context_swap] +[GLOBAL context_swap_to] +; parameters 1 (rdi) pointer to from context +; parameters 2 (rsi) pointer to to context +; struct arch_reg::Context64 +context_swap: + mov [rdi + 8*0], rbx + mov [rdi + 8*1], r12 + mov [rdi + 8*2], r13 + mov [rdi + 8*3], r14 + mov [rdi + 8*4], r15 + mov [rdi + 8*5], rbp + mov [rdi + 8*6], rsp + mov rbx, [rsi + 8*0] + mov r12, [rsi + 8*1] + mov r13, [rsi + 8*2] + mov r14, [rsi + 8*3] + mov r15, [rsi + 8*4] + mov rbp, [rsi + 8*5] + mov rsp, [rsi + 8*6] + ret + +; parameters 1 (rdi) pointer to to context +context_swap_to: + mov rbx, [rdi + 8*0] + mov r12, [rdi + 8*1] + mov r13, [rdi + 8*2] + mov r14, [rdi + 8*3] + mov r15, [rdi + 8*4] + mov rbp, [rdi + 8*5] + mov rsp, [rdi + 8*6] + ret diff --git a/src/arch/x86_64/asm/toc.s b/src/arch/x86_64/asm/toc.s deleted file mode 100644 index e69de29..0000000 --- a/src/arch/x86_64/asm/toc.s +++ /dev/null diff --git a/src/defs.rs b/src/defs.rs index d9a15b5..83ba487 100644 --- a/src/defs.rs +++ b/src/defs.rs @@ -82,6 +82,11 @@ impl Mem { // (64 GiB) pub const KERNEL_HEAP_START: u64 = 0xffff_8030_0000_0000; pub const KERNEL_HEAP_END: u64 = 0xffff_8040_0000_0000; + // unlike the initial "thread" that has 64K stack, new tasks have 4 pages of + // kernel stack. + pub const KERNEL_STACK_SIZE: u64 = 0x4000; + pub const KERNEL_STACK_MASK: u64 = Self::KERNEL_STACK_SIZE - 1; + pub const KERNEL_STACK_TASK_MAGIC: u64 = 0x1A2B3C4D5E6F6969; } // convert VA <-> PA wrt. the kernel id mapping diff --git a/src/proc/mod.rs b/src/proc/mod.rs index cdafe4a..020ac83 100644 --- a/src/proc/mod.rs +++ b/src/proc/mod.rs @@ -1 +1,2 @@ +pub mod sched; pub mod task; diff --git a/src/proc/sched.rs b/src/proc/sched.rs new file mode 100644 index 0000000..8e86c7f --- /dev/null +++ b/src/proc/sched.rs @@ -0,0 +1,17 @@ +use crate::proc::task::*; +use alloc::collections::linked_list::LinkedList; +// TODO the lifetime here is pretty much broken. Fix this later +pub struct Scheduler<'a> { + run_list: LinkedList<&'a Task>, +} + +impl<'a> Scheduler<'a> { + #[inline] + pub fn pop_front(&mut self) -> Option<&Task> { + self.run_list.pop_front() + } + #[inline] + pub fn push_back(&mut self, t: &'a Task) { + self.run_list.push_back(t); + } +} diff --git a/src/proc/task.rs b/src/proc/task.rs index 0ff2065..5cbe2f6 100644 --- a/src/proc/task.rs +++ b/src/proc/task.rs @@ -1,4 +1,7 @@ use crate::arch::x86_64::arch_regs; +use crate::defs::*; +use crate::io::*; +use core::arch::asm; /// currently only kernelSp and Context are important. /// the task struct will be placed on the starting addr (low addr) of the kernel stack. @@ -6,8 +9,48 @@ use crate::arch::x86_64::arch_regs; #[repr(C)] #[repr(packed)] pub struct Task { + pub magic: u64, pub task_id: u32, pub kernel_stack: u64, - pub user_stack: u64, + // pub user_stack: u64, pub context: arch_regs::Context64, + pub state: TaskState, +} + +pub enum TaskState { + Run, + Block, + Dead, + Eating, + Purr, + Meow, + Angry, +} + +#[no_mangle] +pub extern "C" fn _task_entry() -> ! { + println!("I'm Mr.Meeseeks, look at me~"); + unsafe { asm!("hlt") }; + panic!("shoud not reach"); +} + +extern "C" { + fn context_swap(from_ctx: u64, to_ctx: u64); + fn context_swap_to(to_ctx: u64); +} + +impl Task { + /// create new task. This is tricky because the task struct sits at the + /// bottom of the kernel stack, so that you can get the current task by + /// masking the stack pointer. + /// 1. allocate the kernel stack with predefined size and make sure the + /// address is properly aligned + /// 2. cast a task struct onto the stack + /// 3. set whatever fields necessary in the task struct, including a magic + /// 4. create a new stack frame, and update the stack pointer in the context, + /// so that when first swapped to, the task will immediately "return to" + /// the _func_ptr + pub fn new(_id: u32, _func_ptr: u64) -> Self { + todo!() + } } |
