diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 858848a7..c3053f06 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -8,8 +8,9 @@ mod switch; #[allow(clippy::module_inception)] mod task; +use self::id::TaskUserRes; use crate::fs::{open_file, OpenFlags}; -use alloc::sync::Arc; +use alloc::{sync::Arc, vec::Vec}; use lazy_static::*; use manager::fetch_task; use process::ProcessControlBlock; @@ -90,12 +91,21 @@ pub fn exit_current_and_run_next(exit_code: i32) { // deallocate user res (including tid/trap_cx/ustack) of all threads // it has to be done before we dealloc the whole memory_set // otherwise they will be deallocated twice + let mut recycle_res = Vec::::new(); for task in process_inner.tasks.iter().filter(|t| t.is_some()) { let task = task.as_ref().unwrap(); let mut task_inner = task.inner_exclusive_access(); - task_inner.res = None; + if let Some(res) = task_inner.res.take() { + recycle_res.push(res); + } } + // dealloc_tid and dealloc_user_res require access to PCB inner, so we + // need to collect those user res first, then release process_inner + // for now to avoid deadlock/double borrow problem. + drop(process_inner); + recycle_res.clear(); + let mut process_inner = process.inner_exclusive_access(); process_inner.children.clear(); // deallocate other data in user space i.e. program code/data section process_inner.memory_set.recycle_data_pages();