diff --git a/src/arch/x86_64/interrupt/mod.rs b/src/arch/x86_64/interrupt/mod.rs index efc692b..eb0fc3f 100644 --- a/src/arch/x86_64/interrupt/mod.rs +++ b/src/arch/x86_64/interrupt/mod.rs @@ -6,6 +6,19 @@ pub mod consts; pub use self::handler::TrapFrame; +impl TrapFrame { + pub fn new_kernel_thread(entry: extern fn(), rsp: usize) -> Self { + use arch::gdt; + let mut tf = TrapFrame::default(); + tf.iret.cs = gdt::KCODE_SELECTOR.0 as usize; + tf.iret.rip = entry as usize; + tf.iret.ss = gdt::KDATA_SELECTOR.0 as usize; + tf.iret.rsp = rsp; + tf.iret.rflags = 0x282; + tf + } +} + #[inline(always)] pub unsafe fn enable() { x86_64::instructions::interrupts::enable(); diff --git a/src/process.rs b/src/process.rs deleted file mode 100644 index 03a0d72..0000000 --- a/src/process.rs +++ /dev/null @@ -1,156 +0,0 @@ -use alloc::{boxed::Box, string::String, btree_map::BTreeMap}; -use memory::{MemoryController, Stack}; -use spin::{Once, Mutex}; - -/// 平台相关依赖:struct TrapFrame -/// -/// ## 必须实现的特性 -/// -/// * Debug: 用于Debug输出 -use arch::interrupt::TrapFrame; - -pub fn init(mc: &mut MemoryController) { - PROCESSOR.call_once(|| {Mutex::new({ - let mut processor = Processor::new(mc); - let initproc = Process::new_init(mc); - let idleproc = Process::new("idle", idle_thread, mc); - processor.add(initproc); - processor.add(idleproc); - processor - })}); -} - -static PROCESSOR: Once> = Once::new(); - -/// Called by timer handler in arch -/// 设置rsp,指向接下来要执行线程的 内核栈顶 -/// 之后中断处理例程会重置rsp,恢复对应线程的上下文 -pub fn schedule(rsp: &mut usize) { - PROCESSOR.try().unwrap().lock().schedule(rsp); -} - -#[derive(Debug)] -pub struct Process { - pid: Pid, - name: &'static str, - kstack: Stack, -// page_table: Box, - status: Status, - rsp: usize, -} - -#[derive(Debug)] -enum Status { - Uninit, Ready, Running, Sleeping(usize), Exited -} - -struct Processor { - procs: BTreeMap>, - current_pid: Pid, -} - -type Pid = usize; - -impl Processor { - fn new(mc: &mut MemoryController) -> Self { - Processor { - procs: BTreeMap::>::new(), - current_pid: 0, - } - } - fn alloc_pid(&self) -> Pid { - let mut next: Pid = 0; - for &i in self.procs.keys() { - if i != next { - return next; - } else { - next = i + 1; - } - } - return next; - } - fn add(&mut self, mut process: Box) { - let pid = self.alloc_pid(); - process.pid = pid; - self.procs.insert(pid, process); - } - fn schedule(&mut self, rsp: &mut usize) { - let pid = self.find_next(); - self.switch_to(pid, rsp); - } - fn find_next(&self) -> Pid { - *self.procs.keys() - .find(|&&i| i > self.current_pid) - .unwrap_or(self.procs.keys().nth(0).unwrap()) - } - fn switch_to(&mut self, pid: Pid, rsp: &mut usize) { - // for debug print - let pid0 = self.current_pid; - let rsp0 = *rsp; - - if pid == self.current_pid { - return; - } - { - let current = self.procs.get_mut(&self.current_pid).unwrap(); - current.status = Status::Ready; - current.rsp = *rsp; - } - { - let process = self.procs.get_mut(&pid).unwrap(); - process.status = Status::Running; - *rsp = process.rsp; - // TODO switch page table - } - self.current_pid = pid; - debug!("Processor: switch from {} to {}\n rsp: {:#x} -> {:#x}", pid0, pid, rsp0, rsp); - } -} - -impl Process { - /// Make a new kernel thread - fn new(name: &'static str, entry: extern fn(), mc: &mut MemoryController) -> Box { - let kstack = mc.alloc_stack(7).unwrap(); - let rsp = unsafe{ (kstack.top() as *mut TrapFrame).offset(-1) } as usize; - - let mut tf = unsafe{ &mut *(rsp as *mut TrapFrame) }; - - // TODO: move to arch - *tf = TrapFrame::default(); - tf.iret.cs = 8; - tf.iret.rip = entry as usize; - tf.iret.ss = 24; - tf.iret.rsp = kstack.top(); - tf.iret.rflags = 0x282; - - Box::new(Process { - pid: 0, - name, - kstack, - status: Status::Ready, - rsp, - }) - } - /// Make the first kernel thread `initproc` - /// Should be called only once - fn new_init(mc: &mut MemoryController) -> Box { - assert_has_not_been_called!(); - Box::new(Process { - pid: 0, - name: "init", - kstack: mc.kernel_stack.take().unwrap(), - status: Status::Running, - rsp: 0, // will be set at first schedule - }) - } -} - -extern fn idle_thread() { - loop { - println!("idle ..."); - let mut i = 0; - while i < 1 << 22 { - i += 1; - } - } -} \ No newline at end of file diff --git a/src/process/mod.rs b/src/process/mod.rs new file mode 100644 index 0000000..76beeef --- /dev/null +++ b/src/process/mod.rs @@ -0,0 +1,45 @@ +use memory::MemoryController; +use spin::{Once, Mutex}; + +use self::process::*; +use self::processor::*; + +mod process; +mod processor; + +/// 平台相关依赖:struct TrapFrame +/// +/// ## 必须实现的特性 +/// +/// * Debug: 用于Debug输出 +use arch::interrupt::TrapFrame; + +pub fn init(mc: &mut MemoryController) { + PROCESSOR.call_once(|| {Mutex::new({ + let mut processor = Processor::new(mc); + let initproc = Process::new_init(mc); + let idleproc = Process::new("idle", idle_thread, mc); + processor.add(initproc); + processor.add(idleproc); + processor + })}); +} + +static PROCESSOR: Once> = Once::new(); + +/// Called by timer handler in arch +/// 设置rsp,指向接下来要执行线程的 内核栈顶 +/// 之后中断处理例程会重置rsp,恢复对应线程的上下文 +pub fn schedule(rsp: &mut usize) { + PROCESSOR.try().unwrap().lock().schedule(rsp); +} + +extern fn idle_thread() { + loop { + println!("idle ..."); + let mut i = 0; + while i < 1 << 22 { + i += 1; + } + } +} \ No newline at end of file diff --git a/src/process/process.rs b/src/process/process.rs new file mode 100644 index 0000000..5e95e66 --- /dev/null +++ b/src/process/process.rs @@ -0,0 +1,50 @@ +use super::*; +use memory::Stack; + +#[derive(Debug)] +pub struct Process { + pub(in process) pid: Pid, + name: &'static str, + kstack: Stack, + // page_table: Box, + pub(in process) status: Status, + pub(in process) rsp: usize, +} + +pub type Pid = usize; + +#[derive(Debug)] +pub enum Status { + Ready, Running, Sleeping(usize), Exited +} + +impl Process { + /// Make a new kernel thread + pub fn new(name: &'static str, entry: extern fn(), mc: &mut MemoryController) -> Self { + let kstack = mc.alloc_stack(7).unwrap(); + let rsp = unsafe{ (kstack.top() as *mut TrapFrame).offset(-1) } as usize; + + let tf = unsafe{ &mut *(rsp as *mut TrapFrame) }; + *tf = TrapFrame::new_kernel_thread(entry, kstack.top()); + + Process { + pid: 0, + name, + kstack, + status: Status::Ready, + rsp, + } + } + /// Make the first kernel thread `initproc` + /// Should be called only once + pub fn new_init(mc: &mut MemoryController) -> Self { + assert_has_not_been_called!(); + Process { + pid: 0, + name: "init", + kstack: mc.kernel_stack.take().unwrap(), + status: Status::Running, + rsp: 0, // will be set at first schedule + } + } +} \ No newline at end of file diff --git a/src/process/processor.rs b/src/process/processor.rs new file mode 100644 index 0000000..b09e067 --- /dev/null +++ b/src/process/processor.rs @@ -0,0 +1,69 @@ +use alloc::BTreeMap; +use super::*; + +#[derive(Debug)] +pub struct Processor { + procs: BTreeMap, + current_pid: Pid, +} + +impl Processor { + pub fn new(mc: &mut MemoryController) -> Self { + Processor { + procs: BTreeMap::::new(), + current_pid: 0, + } + } + + fn alloc_pid(&self) -> Pid { + let mut next: Pid = 0; + for &i in self.procs.keys() { + if i != next { + return next; + } else { + next = i + 1; + } + } + return next; + } + + pub fn add(&mut self, mut process: Process) { + let pid = self.alloc_pid(); + process.pid = pid; + self.procs.insert(pid, process); + } + + pub fn schedule(&mut self, rsp: &mut usize) { + let pid = self.find_next(); + self.switch_to(pid, rsp); + } + + fn find_next(&self) -> Pid { + *self.procs.keys() + .find(|&&i| i > self.current_pid) + .unwrap_or(self.procs.keys().nth(0).unwrap()) + } + + fn switch_to(&mut self, pid: Pid, rsp: &mut usize) { + // for debug print + let pid0 = self.current_pid; + let rsp0 = *rsp; + + if pid == self.current_pid { + return; + } + { + let current = self.procs.get_mut(&self.current_pid).unwrap(); + current.status = Status::Ready; + current.rsp = *rsp; + } + { + let process = self.procs.get_mut(&pid).unwrap(); + process.status = Status::Running; + *rsp = process.rsp; + // TODO switch page table + } + self.current_pid = pid; + debug!("Processor: switch from {} to {}\n rsp: {:#x} -> {:#x}", pid0, pid, rsp0, rsp); + } +} \ No newline at end of file