diff --git a/crate/process/src/lib.rs b/crate/process/src/lib.rs index 625e2b6..1141518 100644 --- a/crate/process/src/lib.rs +++ b/crate/process/src/lib.rs @@ -12,8 +12,12 @@ extern crate spin; #[macro_use] extern crate std; -pub mod processor; +mod process_manager; +mod processor; pub mod scheduler; pub mod thread; mod util; mod event_hub; + +pub use process_manager::*; +pub use processor::Processor; diff --git a/crate/process/src/process_manager.rs b/crate/process/src/process_manager.rs new file mode 100644 index 0000000..dd8dab5 --- /dev/null +++ b/crate/process/src/process_manager.rs @@ -0,0 +1,120 @@ +use alloc::boxed::Box; +use alloc::sync::Arc; +use spin::Mutex; +use scheduler::Scheduler; +use core::cell::UnsafeCell; + +struct Process { + id: Pid, + status: Status, + status_after_stop: Status, + context: Option>, +} + +pub type Pid = usize; +type ExitCode = usize; +const MAX_PROC_NUM: usize = 32; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum Status { + Ready, + Running(usize), + Waiting(Pid), + Sleeping, + Exited(ExitCode), +} + +pub trait Context { + unsafe fn switch_to(&mut self, target: &mut Context); +} + +pub struct ProcessManager { + procs: [Mutex>; MAX_PROC_NUM], + scheduler: Mutex>, +} + +impl ProcessManager { + pub fn new(scheduler: Box) -> Self { + ProcessManager { + procs: Default::default(), + scheduler: Mutex::new(scheduler), + } + } + + fn alloc_pid(&self) -> Pid { + for i in 0..MAX_PROC_NUM { + if self.procs[i].lock().is_none() { + return i; + } + } + panic!("Process number exceeded"); + } + + /// Add a new process + pub fn add(&self, context: Box) -> Pid { + let pid = self.alloc_pid(); + // TODO: check parent + *self.procs[pid].lock() = Some(Process { + id: pid, + status: Status::Ready, + status_after_stop: Status::Ready, + context: Some(context), + }); + self.scheduler.lock().insert(pid); + pid + } + + /// Make process `pid` time slice -= 1. + /// Return true if time slice == 0. + /// Called by timer interrupt handler. + pub fn tick(&self, pid: Pid) -> bool { + self.scheduler.lock().tick(pid) + } + + /// Called by Processor to get a process to run. + /// The manager first mark it `Running`, + /// then take out and return its Context. + pub fn run(&self, cpu_id: usize) -> (Pid, Box) { + let mut scheduler = self.scheduler.lock(); + let pid = scheduler.select() + .expect("failed to select a runnable process"); + scheduler.remove(pid); + let mut proc_lock = self.procs[pid].lock(); + let mut proc = proc_lock.as_mut().unwrap(); + proc.status = Status::Running(cpu_id); + (pid, proc.context.take().unwrap()) + } + + /// Called by Processor to finish running a process + /// and give its context back. + pub fn stop(&self, pid: Pid, context: Box) { + let mut proc_lock = self.procs[pid].lock(); + let mut proc = proc_lock.as_mut().unwrap(); + proc.status = proc.status_after_stop.clone(); + proc.status_after_stop = Status::Ready; + proc.context = Some(context); + if proc.status == Status::Ready { + self.scheduler.lock().insert(pid); + } + } + + /// Switch the status of a process. + /// Insert/Remove it to/from scheduler if necessary. + pub fn set_status(&self, pid: Pid, status: Status) { + let mut scheduler = self.scheduler.lock(); + let mut proc_lock = self.procs[pid].lock(); + let mut proc = proc_lock.as_mut().unwrap(); + match (&proc.status, &status) { + (Status::Ready, Status::Ready) => return, + (Status::Ready, _) => scheduler.remove(pid), + (Status::Running(_), _) => {}, + (_, Status::Ready) => scheduler.insert(pid), + _ => {} + } + trace!("process {} {:?} -> {:?}", pid, proc.status, status); + match proc.status { + Status::Running(_) => proc.status_after_stop = status, + _ => proc.status = status, + } + } +} diff --git a/crate/process/src/processor.rs b/crate/process/src/processor.rs index 8de3075..4fc3e18 100644 --- a/crate/process/src/processor.rs +++ b/crate/process/src/processor.rs @@ -1,9 +1,8 @@ use alloc::boxed::Box; -use alloc::vec::Vec; use alloc::sync::Arc; use spin::Mutex; -use scheduler::Scheduler; use core::cell::UnsafeCell; +use process_manager::*; /// Process executor /// @@ -90,119 +89,3 @@ impl Processor { } } } - -struct Process { - id: Pid, - status: Status, - status_after_stop: Status, - context: Option>, -} - -type Pid = usize; -type ExitCode = usize; -const MAX_PROC_NUM: usize = 32; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Status { - Ready, - Running(usize), - Waiting(Pid), - Sleeping, - Exited(ExitCode), -} - -pub trait Context { - unsafe fn switch_to(&mut self, target: &mut Context); -} - -pub struct ProcessManager { - procs: [Mutex>; MAX_PROC_NUM], - scheduler: Mutex>, -} - -impl ProcessManager { - - pub fn new(scheduler: Box) -> Self { - ProcessManager { - procs: Default::default(), - scheduler: Mutex::new(scheduler), - } - } - - fn alloc_pid(&self) -> Pid { - for i in 0..MAX_PROC_NUM { - if self.procs[i].lock().is_none() { - return i; - } - } - panic!("Process number exceeded"); - } - - /// Add a new process - pub fn add(&self, context: Box) -> Pid { - let pid = self.alloc_pid(); - // TODO: check parent - *self.procs[pid].lock() = Some(Process { - id: pid, - status: Status::Ready, - status_after_stop: Status::Ready, - context: Some(context), - }); - self.scheduler.lock().insert(pid); - pid - } - - /// Make process `pid` time slice -= 1. - /// Return true if time slice == 0. - /// Called by timer interrupt handler. - pub fn tick(&self, pid: Pid) -> bool { - self.scheduler.lock().tick(pid) - } - - /// Called by Processor to get a process to run. - /// The manager first mark it `Running`, - /// then take out and return its Context. - pub fn run(&self, cpu_id: usize) -> (Pid, Box) { - let mut scheduler = self.scheduler.lock(); - let pid = scheduler.select() - .expect("failed to select a runnable process"); - scheduler.remove(pid); - let mut proc_lock = self.procs[pid].lock(); - let mut proc = proc_lock.as_mut().unwrap(); - proc.status = Status::Running(cpu_id); - (pid, proc.context.take().unwrap()) - } - - /// Called by Processor to finish running a process - /// and give its context back. - pub fn stop(&self, pid: Pid, context: Box) { - let mut proc_lock = self.procs[pid].lock(); - let mut proc = proc_lock.as_mut().unwrap(); - proc.status = proc.status_after_stop.clone(); - proc.status_after_stop = Status::Ready; - proc.context = Some(context); - if proc.status == Status::Ready { - self.scheduler.lock().insert(pid); - } - } - - /// Switch the status of a process. - /// Insert/Remove it to/from scheduler if necessary. - pub fn set_status(&self, pid: Pid, status: Status) { - let mut scheduler = self.scheduler.lock(); - let mut proc_lock = self.procs[pid].lock(); - let mut proc = proc_lock.as_mut().unwrap(); - match (&proc.status, &status) { - (Status::Ready, Status::Ready) => return, - (Status::Ready, _) => scheduler.remove(pid), - (Status::Running(_), _) => {}, - (_, Status::Ready) => scheduler.insert(pid), - _ => {} - } - trace!("process {} {:?} -> {:?}", pid, proc.status, status); - match proc.status { - Status::Running(_) => proc.status_after_stop = status, - _ => proc.status = status, - } - } -} \ No newline at end of file diff --git a/crate/process/src/thread.rs b/crate/process/src/thread.rs index b72ebfe..1833af3 100644 --- a/crate/process/src/thread.rs +++ b/crate/process/src/thread.rs @@ -28,12 +28,11 @@ use alloc::boxed::Box; use alloc::collections::BTreeMap; -use core::any::Any; use core::marker::PhantomData; use core::ptr; use core::time::Duration; -use core::ops::DerefMut; use processor::*; +use process_manager::*; use scheduler::Scheduler; /// All dependencies for thread mod. diff --git a/kernel/src/process/context.rs b/kernel/src/process/context.rs index eb311e4..e078219 100644 --- a/kernel/src/process/context.rs +++ b/kernel/src/process/context.rs @@ -2,7 +2,7 @@ use arch::interrupt::{TrapFrame, Context as ArchContext}; use memory::{MemoryArea, MemoryAttr, MemorySet}; use xmas_elf::{ElfFile, header, program::{Flags, ProgramHeader, Type}}; use core::fmt::{Debug, Error, Formatter}; -use ucore_process::processor::Context; +use ucore_process::Context; use alloc::boxed::Box; pub struct ContextImpl { diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 5bc17a3..0e13b33 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -1,8 +1,7 @@ use spin::Once; use sync::{SpinNoIrqLock, Mutex, MutexGuard, SpinNoIrq}; pub use self::context::ContextImpl; -pub use ucore_process::processor::*; -pub use ucore_process::scheduler::*; +pub use ucore_process::*; pub use ucore_process::thread::*; use alloc::boxed::Box; use consts::MAX_CPU_NUM; @@ -14,7 +13,7 @@ mod context; pub fn init() { // NOTE: max_time_slice <= 5 to ensure 'priority' test pass - let scheduler = Box::new(RRScheduler::new(5)); + let scheduler = Box::new(scheduler::RRScheduler::new(5)); let manager = Arc::new(ProcessManager::new(scheduler)); extern fn idle(_arg: usize) -> ! {