From 3d45b8f8a0c34eb9a8f272cfd57fd117d47944a1 Mon Sep 17 00:00:00 2001
From: sslime336 <sslime@yeah.net>
Date: Sun, 30 Jul 2023 16:04:57 +0800
Subject: [PATCH] Feat: child res recycler

---
 kernel/src/task/manager.rs            | 22 +++++++++++++++++++++
 kernel/src/task/mod.rs                | 10 +++++++++-
 kernel/src/task/processor/mod.rs      | 13 ++++++++++++-
 kernel/src/task/processor/schedule.rs |  4 +++-
 kernel/src/task/task.rs               | 28 +++++++++++++++++++++++----
 5 files changed, 70 insertions(+), 7 deletions(-)

diff --git a/kernel/src/task/manager.rs b/kernel/src/task/manager.rs
index 3c816559..092913c8 100644
--- a/kernel/src/task/manager.rs
+++ b/kernel/src/task/manager.rs
@@ -1,4 +1,5 @@
 use crate::timer::get_time_ms;
+use alloc::vec::Vec;
 use sync_cell::SyncRefCell;
 
 use super::TaskControlBlock;
@@ -6,6 +7,27 @@ use alloc::collections::{BTreeMap, BinaryHeap, VecDeque};
 use alloc::sync::Arc;
 use spin::Mutex;
 
+pub struct ChildrenThreadMonitor {
+    cancelled_child_threads: Vec<Arc<TaskControlBlock>>,
+}
+
+impl ChildrenThreadMonitor {
+    pub const fn new() -> Self {
+        ChildrenThreadMonitor {
+            cancelled_child_threads: Vec::new(),
+        }
+    }
+    pub fn take(&mut self, child_thread: Arc<TaskControlBlock>) {
+        self.cancelled_child_threads.push(child_thread);
+    }
+    pub fn release_all(&mut self){
+        self.cancelled_child_threads.clear();
+    }
+}
+
+pub static CHILDREN_THREAD_MONITOR: Mutex<ChildrenThreadMonitor> =
+    Mutex::new(ChildrenThreadMonitor::new());
+
 /// FIFO 任务管理器
 pub struct TaskManager {
     ready_queue: VecDeque<Arc<TaskControlBlock>>, // status: Ready
diff --git a/kernel/src/task/mod.rs b/kernel/src/task/mod.rs
index 1ca3c8bd..ecd1ace4 100644
--- a/kernel/src/task/mod.rs
+++ b/kernel/src/task/mod.rs
@@ -34,7 +34,7 @@ use crate::{
 use self::{
     initproc::INITPROC,
     manager::block_task,
-    processor::{acquire_processor, schedule},
+    processor::{acquire_processor, schedule, take_cancelled_chiled_thread},
 };
 
 /// 将当前任务置为就绪态,放回到进程管理器中的就绪队列中,重新选择一个进程运行
@@ -64,6 +64,14 @@ pub fn exit_current_and_run_next(exit_code: i32) {
     // 获取访问权限,修改进程状态
     let task = take_current_task().unwrap();
     remove_from_pid2task(task.pid());
+
+    if task.is_child_thread() {
+        take_cancelled_chiled_thread(task);
+        let mut _unused = TaskContext::empty();
+        schedule(&mut _unused as *mut _);
+        unreachable!()
+    }
+
     let mut inner = task.inner_mut();
     // memory_set mut borrow
     let mut ms_mut = task.memory_set.write();
diff --git a/kernel/src/task/processor/mod.rs b/kernel/src/task/processor/mod.rs
index e9314648..ece49ef5 100644
--- a/kernel/src/task/processor/mod.rs
+++ b/kernel/src/task/processor/mod.rs
@@ -14,7 +14,9 @@ pub use schedule::*;
 
 use crate::{mm::memory_set, trap::TrapContext};
 
-use super::{switch::__switch, task::TaskControlBlock, TaskContext};
+use super::{
+    manager::CHILDREN_THREAD_MONITOR, switch::__switch, task::TaskControlBlock, TaskContext,
+};
 
 /// 从全局变量 `PROCESSOR` 中取出当前正在执行的任务
 pub fn take_current_task() -> Option<Arc<TaskControlBlock>> {
@@ -48,3 +50,12 @@ pub fn schedule(switched_task_cx_ptr: *mut TaskContext) {
 
     unsafe { __switch(switched_task_cx_ptr, idle_task_cx_ptr) }
 }
+
+/// 回收已 cancel 的子线程资源
+pub fn recycle_child_threads_res() {
+    CHILDREN_THREAD_MONITOR.lock().release_all();
+}
+
+pub fn take_cancelled_chiled_thread(child_thread: Arc<TaskControlBlock>) {
+    CHILDREN_THREAD_MONITOR.lock().take(child_thread);
+}
diff --git a/kernel/src/task/processor/schedule.rs b/kernel/src/task/processor/schedule.rs
index 85af1195..0499da81 100644
--- a/kernel/src/task/processor/schedule.rs
+++ b/kernel/src/task/processor/schedule.rs
@@ -14,7 +14,7 @@ use crate::task::{
     unblock_task, TaskContext, TaskControlBlock,
 };
 
-use super::{acquire_processor, Processor};
+use super::{acquire_processor, Processor, recycle_child_threads_res};
 
 /// 进入 idle 控制流,它运行在这个 CPU 核的启动栈上,
 /// 功能是循环调用 fetch_task 直到顺利从任务管理器中取出一个任务,随后便准备通过任务切换的方式来执行
@@ -22,6 +22,8 @@ pub fn run_tasks() {
     loop {
         let processor = acquire_processor();
 
+        recycle_child_threads_res();
+
         if let Some(hanging_task) = check_hanging() {
             run_task(hanging_task, processor);
         } else if let Some(interupt_task) = check_interupt() {
diff --git a/kernel/src/task/task.rs b/kernel/src/task/task.rs
index 2113026e..debf0d12 100644
--- a/kernel/src/task/task.rs
+++ b/kernel/src/task/task.rs
@@ -44,6 +44,13 @@ pub struct TaskControlBlock {
     inner: RwLock<TaskControlBlockInner>,
 }
 
+impl TaskControlBlock {
+    #[inline]
+    pub fn is_child_thread(&self) -> bool {
+        self.pid.0 != self.tgid
+    }
+}
+
 impl Debug for TaskControlBlock {
     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
         f.debug_struct("TaskControlBlock")
@@ -324,7 +331,11 @@ impl TaskControlBlock {
 
         // padding 0 表示结束
         user_sp -= core::mem::size_of::<usize>();
-        copyout(token, unsafe { (user_sp as *mut usize).as_mut().unwrap() }, &0);
+        copyout(
+            token,
+            unsafe { (user_sp as *mut usize).as_mut().unwrap() },
+            &0,
+        );
 
         // envs_ptr
         user_sp -= (envs.len()) * core::mem::size_of::<usize>();
@@ -343,7 +354,11 @@ impl TaskControlBlock {
 
         // padding 0 表示结束
         user_sp -= core::mem::size_of::<usize>();
-        copyout(token, unsafe { (user_sp as *mut usize).as_mut().unwrap() }, &0);
+        copyout(
+            token,
+            unsafe { (user_sp as *mut usize).as_mut().unwrap() },
+            &0,
+        );
 
         // args_ptr
         user_sp -= (args.len()) * core::mem::size_of::<usize>();
@@ -351,8 +366,13 @@ impl TaskControlBlock {
         for i in 0..args.len() {
             copyout(
                 token,
-                unsafe { ((args_ptr_base + i * core::mem::size_of::<usize>()) as *mut usize).as_mut().unwrap() },
-            &args_ptrv[i]);
+                unsafe {
+                    ((args_ptr_base + i * core::mem::size_of::<usize>()) as *mut usize)
+                        .as_mut()
+                        .unwrap()
+                },
+                &args_ptrv[i],
+            );
         }
 
         // argc
-- 
GitLab