aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTianhao Wang <shrik3@mailbox.org>2024-06-06 02:08:21 +0200
committerTianhao Wang <shrik3@mailbox.org>2024-06-11 15:17:14 +0200
commitd495a1745c83a8186bf1c6c531177887dd245436 (patch)
tree5ea93adceea22d7aa12eb0165fce80e458dd3864
parenta86f59b32eb86a1ccb94bf1e627c1115c3b6b217 (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.s35
-rw-r--r--src/arch/x86_64/asm/toc.s0
-rw-r--r--src/defs.rs5
-rw-r--r--src/proc/mod.rs1
-rw-r--r--src/proc/sched.rs17
-rw-r--r--src/proc/task.rs45
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!()
+ }
}