diff --git a/os/src/task/manager.rs b/os/src/task/manager.rs index 5ed68ae7..bdeda5d2 100644 --- a/os/src/task/manager.rs +++ b/os/src/task/manager.rs @@ -21,6 +21,14 @@ impl TaskManager { pub fn fetch(&mut self) -> Option> { self.ready_queue.pop_front() } + pub fn remove(&mut self, task: Arc) { + if let Some((id, _)) = self.ready_queue + .iter() + .enumerate() + .find(|(_, t)| Arc::as_ptr(t) == Arc::as_ptr(&task)) { + self.ready_queue.remove(id); + } + } } lazy_static! { @@ -34,6 +42,10 @@ pub fn add_task(task: Arc) { TASK_MANAGER.exclusive_access().add(task); } +pub fn remove_task(task: Arc) { + TASK_MANAGER.exclusive_access().remove(task); +} + pub fn fetch_task() -> Option> { TASK_MANAGER.exclusive_access().fetch() } diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 995a3374..b66490b8 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -15,10 +15,11 @@ use lazy_static::*; use manager::fetch_task; use process::ProcessControlBlock; use switch::__switch; +use crate::timer::remove_timer; pub use context::TaskContext; pub use id::{kstack_alloc, pid_alloc, KernelStack, PidHandle}; -pub use manager::{add_task, pid2process, remove_from_pid2process}; +pub use manager::{add_task, remove_task, pid2process, remove_from_pid2process}; pub use processor::{ current_kstack_top, current_process, current_task, current_trap_cx, current_trap_cx_user_va, current_user_token, run_tasks, schedule, take_current_task, @@ -90,6 +91,9 @@ pub fn exit_current_and_run_next(exit_code: i32) { let mut recycle_res = Vec::::new(); for task in process_inner.tasks.iter().filter(|t| t.is_some()) { let task = task.as_ref().unwrap(); + // if other tasks are Ready in TaskManager or waiting for a timer to be + // expired, we should remove them. + remove_inactive_task(Arc::clone(&task)); let mut task_inner = task.inner_exclusive_access(); if let Some(res) = task_inner.res.take() { recycle_res.push(res); @@ -107,6 +111,8 @@ pub fn exit_current_and_run_next(exit_code: i32) { process_inner.memory_set.recycle_data_pages(); // drop file descriptors process_inner.fd_table.clear(); + // remove all tasks + process_inner.tasks.clear(); } drop(process); // we do not have to save task context @@ -137,3 +143,8 @@ pub fn current_add_signal(signal: SignalFlags) { let mut process_inner = process.inner_exclusive_access(); process_inner.signals |= signal; } + +pub fn remove_inactive_task(task: Arc) { + remove_task(Arc::clone(&task)); + remove_timer(Arc::clone(&task)); +} diff --git a/os/src/timer.rs b/os/src/timer.rs index 3baed0f7..720caf76 100644 --- a/os/src/timer.rs +++ b/os/src/timer.rs @@ -59,6 +59,18 @@ pub fn add_timer(expire_ms: usize, task: Arc) { timers.push(TimerCondVar { expire_ms, task }); } +pub fn remove_timer(task: Arc) { + let mut timers = TIMERS.exclusive_access(); + let mut temp = BinaryHeap::::new(); + for condvar in timers.drain() { + if Arc::as_ptr(&task) != Arc::as_ptr(&condvar.task) { + temp.push(condvar); + } + } + timers.clear(); + timers.append(&mut temp); +} + pub fn check_timer() { let current_ms = get_time_ms(); let mut timers = TIMERS.exclusive_access(); diff --git a/user/src/bin/early_exit.rs b/user/src/bin/early_exit.rs index a81e55d3..dea35fbe 100644 --- a/user/src/bin/early_exit.rs +++ b/user/src/bin/early_exit.rs @@ -5,7 +5,6 @@ extern crate user_lib; extern crate alloc; -use alloc::vec::Vec; use user_lib::{exit, thread_create}; pub fn thread_a() -> ! { diff --git a/user/src/bin/early_exit2.rs b/user/src/bin/early_exit2.rs new file mode 100644 index 00000000..4fd75d7f --- /dev/null +++ b/user/src/bin/early_exit2.rs @@ -0,0 +1,24 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use user_lib::{exit, thread_create, sleep}; + +pub fn thread_a() -> ! { + println!("into thread_a"); + sleep(1000); + // the following message cannot be seen since the main thread has exited before + println!("exit thread_a"); + exit(1) +} + +#[no_mangle] +pub fn main() -> i32 { + thread_create(thread_a as usize, 0); + sleep(100); + println!("main thread exited."); + exit(0) +}