diff --git a/crate/process/src/event_hub.rs b/crate/process/src/event_hub.rs index f826cd0..97fa80c 100644 --- a/crate/process/src/event_hub.rs +++ b/crate/process/src/event_hub.rs @@ -1,4 +1,4 @@ -use alloc::collections::BinaryHeap; +use alloc::collections::VecDeque; use core::cmp::{Ordering, PartialOrd}; type Time = usize; @@ -30,32 +30,63 @@ impl Ord for Timer { pub struct EventHub { tick: Time, - timers: BinaryHeap>, + timers: VecDeque>, } -impl EventHub { +impl EventHub { pub fn new() -> Self { EventHub { tick: 0, - timers: BinaryHeap::new(), + timers: VecDeque::new(), } } pub fn tick(&mut self) { self.tick += 1; } pub fn pop(&mut self) -> Option { - match self.timers.peek() { + match self.timers.front() { None => 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) { + //debug!("{:?} {:?}", 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 { 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); + } + } } \ No newline at end of file diff --git a/crate/process/src/process_manager.rs b/crate/process/src/process_manager.rs index 2142ec3..b8931e7 100644 --- a/crate/process/src/process_manager.rs +++ b/crate/process/src/process_manager.rs @@ -26,10 +26,11 @@ pub enum Status { Exited(ExitCode), } +#[derive(Eq, PartialEq)] enum Event { Wakeup(Pid), + Dropped, } - pub trait Context { unsafe fn switch_to(&mut self, target: &mut Context); } @@ -84,6 +85,7 @@ impl ProcessManager { while let Some(event) = event_hub.pop() { match event { Event::Wakeup(pid) => self.set_status(pid, Status::Ready), + Event::Dropped => {}, } } self.scheduler.lock().tick(pid) @@ -126,20 +128,22 @@ impl ProcessManager { /// Switch the status of a process. /// Insert/Remove it to/from scheduler if necessary. 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().expect("process not exist"); trace!("process {} {:?} -> {:?}", pid, proc.status, status); - match (&proc.status, &status) { - (Status::Ready, Status::Ready) => return, - (Status::Ready, _) => scheduler.remove(pid), - (Status::Running(_), _) => {}, - (Status::Exited(_), _) => panic!("can not set status for a exited process"), - (Status::Waiting(target), Status::Exited(_)) => - self.wait_queue[*target].lock().retain(|&i| i != pid), - // TODO: Sleep -> Exited Remove wakeup event. - (_, Status::Ready) => scheduler.insert(pid), - _ => {} + { // limit the lifetime of scheduler + let mut scheduler = self.scheduler.lock(); + match (&proc.status, &status) { + (Status::Ready, Status::Ready) => return, + (Status::Ready, _) => scheduler.remove(pid), + (Status::Running(_), _) => {}, + (Status::Exited(_), _) => panic!("can not set status for a exited process"), + (Status::Waiting(target), Status::Exited(_)) => + 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 { 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); + let time = if time_raw >= (1 << 31) {0} else {time_raw}; if time != 0 { self.event_hub.lock().push(time, Event::Wakeup(pid)); } @@ -183,7 +188,7 @@ impl ProcessManager { pub fn exit(&self, pid: Pid, code: ExitCode) { self.set_status(pid, Status::Exited(code)); - } + } /// Called when a process exit fn exit_handler(&self, pid: Pid, proc: &mut Process) { for waiter in self.wait_queue[pid].lock().drain(..) { diff --git a/crate/riscv b/crate/riscv index a37a65f..f358204 160000 --- a/crate/riscv +++ b/crate/riscv @@ -1 +1 @@ -Subproject commit a37a65fa13a00c5aa0068c3f2b5d55af6a37dd93 +Subproject commit f358204af01f2374ab6ed6ea059f724cd5f2fe6f diff --git a/kernel/src/fs.rs b/kernel/src/fs.rs index 8e1b7aa..938dff2 100644 --- a/kernel/src/fs.rs +++ b/kernel/src/fs.rs @@ -45,8 +45,12 @@ pub fn shell() { // start interaction loop { print!(">> "); + use console::get_line; let name = get_line(); + //use alloc::prelude::ToString; + //let name = "waitkill".to_string(); + if name == "" { continue; } diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 2601216..bcc9bf7 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -113,7 +113,7 @@ fn sys_yield() -> i32 { /// Kill the process fn sys_kill(pid: usize) -> i32 { - info!("kill: {}", pid); + info!("{} killed: {}", thread::current().id(), pid); processor().manager().exit(pid, 0x100); if pid == thread::current().id() { processor().yield_now();