parent
0553d3374d
commit
6e157ee97d
@ -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<PageTable>,
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
use alloc::BTreeMap;
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Processor {
|
||||
procs: BTreeMap<Pid, Process>,
|
||||
current_pid: Pid,
|
||||
}
|
||||
|
||||
impl Processor {
|
||||
pub fn new(mc: &mut MemoryController) -> Self {
|
||||
Processor {
|
||||
procs: BTreeMap::<Pid, Process>::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);
|
||||
}
|
||||
}
|
Loading…
Reference in new issue