debug for sleepkill

master
chenqiuhao 6 years ago
parent 5ee44588e0
commit 8d6d3b7c37

@ -1,4 +1,4 @@
use alloc::collections::BinaryHeap; use alloc::collections::VecDeque;
use core::cmp::{Ordering, PartialOrd}; use core::cmp::{Ordering, PartialOrd};
type Time = usize; type Time = usize;
@ -30,32 +30,63 @@ impl<T> Ord for Timer<T> {
pub struct EventHub<T> { pub struct EventHub<T> {
tick: Time, tick: Time,
timers: BinaryHeap<Timer<T>>, timers: VecDeque<Timer<T>>,
} }
impl<T> EventHub<T> { impl<T: PartialEq> EventHub<T> {
pub fn new() -> Self { pub fn new() -> Self {
EventHub { EventHub {
tick: 0, tick: 0,
timers: BinaryHeap::new(), timers: VecDeque::new(),
} }
} }
pub fn tick(&mut self) { pub fn tick(&mut self) {
self.tick += 1; self.tick += 1;
} }
pub fn pop(&mut self) -> Option<T> { pub fn pop(&mut self) -> Option<T> {
match self.timers.peek() { match self.timers.front() {
None => return None, None => return None,
Some(timer) if timer.time != self.tick => return None, Some(timer) if timer.time != self.tick => return None,
_ => {} _ => {}
}; };
self.timers.pop().map(|t| t.data) self.timers.pop_front().map(|t| t.data)
} }
pub fn push(&mut self, time_after: Time, data: T) { pub fn push(&mut self, time_after: Time, data: T) {
//debug!("{:?} {:?}", self.tick, time_after);
let time = self.tick + time_after; let time = self.tick + time_after;
self.timers.push(Timer { time, data }); let timer = Timer { time, data };
let mut it = self.timers.iter();
let mut i : usize = 0;
loop {
let now = it.next();
if now == None {
break
};
if now.unwrap() < &timer {
break
};
i += 1;
}
self.timers.insert(i, timer);
} }
pub fn get_time(&self) -> Time { pub fn get_time(&self) -> Time {
self.tick self.tick
} }
pub fn remove(&mut self, data: T) {
let mut it = self.timers.iter();
let mut i : usize = 0;
loop {
let now = it.next();
if now == None {
break
};
if now.map(|t| &t.data).unwrap() == &data {
break
};
i += 1;
}
if i < self.timers.len() {
self.timers.remove(i);
}
}
} }

@ -26,10 +26,11 @@ pub enum Status {
Exited(ExitCode), Exited(ExitCode),
} }
#[derive(Eq, PartialEq)]
enum Event { enum Event {
Wakeup(Pid), Wakeup(Pid),
Dropped,
} }
pub trait Context { pub trait Context {
unsafe fn switch_to(&mut self, target: &mut Context); unsafe fn switch_to(&mut self, target: &mut Context);
} }
@ -84,6 +85,7 @@ impl ProcessManager {
while let Some(event) = event_hub.pop() { while let Some(event) = event_hub.pop() {
match event { match event {
Event::Wakeup(pid) => self.set_status(pid, Status::Ready), Event::Wakeup(pid) => self.set_status(pid, Status::Ready),
Event::Dropped => {},
} }
} }
self.scheduler.lock().tick(pid) self.scheduler.lock().tick(pid)
@ -126,20 +128,22 @@ impl ProcessManager {
/// Switch the status of a process. /// Switch the status of a process.
/// Insert/Remove it to/from scheduler if necessary. /// Insert/Remove it to/from scheduler if necessary.
fn set_status(&self, pid: Pid, status: Status) { 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_lock = self.procs[pid].lock();
let mut proc = proc_lock.as_mut().expect("process not exist"); let mut proc = proc_lock.as_mut().expect("process not exist");
trace!("process {} {:?} -> {:?}", pid, proc.status, status); trace!("process {} {:?} -> {:?}", pid, proc.status, status);
match (&proc.status, &status) { { // limit the lifetime of scheduler
(Status::Ready, Status::Ready) => return, let mut scheduler = self.scheduler.lock();
(Status::Ready, _) => scheduler.remove(pid), match (&proc.status, &status) {
(Status::Running(_), _) => {}, (Status::Ready, Status::Ready) => return,
(Status::Exited(_), _) => panic!("can not set status for a exited process"), (Status::Ready, _) => scheduler.remove(pid),
(Status::Waiting(target), Status::Exited(_)) => (Status::Running(_), _) => {},
self.wait_queue[*target].lock().retain(|&i| i != pid), (Status::Exited(_), _) => panic!("can not set status for a exited process"),
// TODO: Sleep -> Exited Remove wakeup event. (Status::Waiting(target), Status::Exited(_)) =>
(_, Status::Ready) => scheduler.insert(pid), self.wait_queue[*target].lock().retain(|&i| i != pid),
_ => {} (Status::Sleeping, Status::Exited(_)) => self.event_hub.lock().remove(Event::Wakeup(pid)),
(_, Status::Ready) => scheduler.insert(pid),
_ => {}
}
} }
match proc.status { match proc.status {
Status::Running(_) => proc.status_after_stop = status, Status::Running(_) => proc.status_after_stop = status,
@ -165,8 +169,9 @@ impl ProcessManager {
} }
} }
pub fn sleep(&self, pid: Pid, time: usize) { pub fn sleep(&self, pid: Pid, time_raw: usize) {
self.set_status(pid, Status::Sleeping); self.set_status(pid, Status::Sleeping);
let time = if time_raw >= (1 << 31) {0} else {time_raw};
if time != 0 { if time != 0 {
self.event_hub.lock().push(time, Event::Wakeup(pid)); self.event_hub.lock().push(time, Event::Wakeup(pid));
} }
@ -183,7 +188,7 @@ impl ProcessManager {
pub fn exit(&self, pid: Pid, code: ExitCode) { pub fn exit(&self, pid: Pid, code: ExitCode) {
self.set_status(pid, Status::Exited(code)); self.set_status(pid, Status::Exited(code));
} }
/// Called when a process exit /// Called when a process exit
fn exit_handler(&self, pid: Pid, proc: &mut Process) { fn exit_handler(&self, pid: Pid, proc: &mut Process) {
for waiter in self.wait_queue[pid].lock().drain(..) { for waiter in self.wait_queue[pid].lock().drain(..) {

@ -1 +1 @@
Subproject commit a37a65fa13a00c5aa0068c3f2b5d55af6a37dd93 Subproject commit f358204af01f2374ab6ed6ea059f724cd5f2fe6f

@ -45,8 +45,12 @@ pub fn shell() {
// start interaction // start interaction
loop { loop {
print!(">> "); print!(">> ");
use console::get_line; use console::get_line;
let name = get_line(); let name = get_line();
//use alloc::prelude::ToString;
//let name = "waitkill".to_string();
if name == "" { if name == "" {
continue; continue;
} }

@ -113,7 +113,7 @@ fn sys_yield() -> i32 {
/// Kill the process /// Kill the process
fn sys_kill(pid: usize) -> i32 { fn sys_kill(pid: usize) -> i32 {
info!("kill: {}", pid); info!("{} killed: {}", thread::current().id(), pid);
processor().manager().exit(pid, 0x100); processor().manager().exit(pid, 0x100);
if pid == thread::current().id() { if pid == thread::current().id() {
processor().yield_now(); processor().yield_now();

Loading…
Cancel
Save