os/kernel/task/
task_manager.rs1use alloc::collections::btree_map::BTreeMap;
10use alloc::vec::Vec;
11
12use crate::kernel::task::SharedTask;
13use crate::kernel::task::tid_allocator::TidAllocator;
14use crate::kernel::{TaskState, exit_task_with_block, wake_up_with_block};
15use crate::sync::SpinLock;
16use crate::uapi::signal::SignalFlags;
17
18use lazy_static::lazy_static;
19
20lazy_static! {
21 pub static ref TASK_MANAGER: SpinLock<TaskManager> = SpinLock::new(TaskManager::new());
22}
23
24pub trait TaskManagerTrait {
33 fn new() -> Self;
37
38 fn allocate_tid(&mut self) -> u32;
41
42 fn add_task(&mut self, task: SharedTask);
46
47 fn exit_task(&mut self, task: SharedTask, code: i32);
51
52 fn release_task(&mut self, task: SharedTask);
56
57 fn get_task(&self, tid: u32) -> Option<SharedTask>;
62
63 fn get_task_cond(&self, cond: impl Fn(&SharedTask) -> bool) -> Vec<SharedTask>;
68
69 fn get_process_threads(&self, process: SharedTask) -> Vec<SharedTask>;
74
75 fn get_process_children(&self, process: SharedTask) -> Vec<SharedTask>;
80
81 fn send_signal(&self, task: SharedTask, signal: usize) -> bool;
87
88 fn get_all_tasks(&self) -> Vec<SharedTask>;
91
92 #[cfg(test)]
93 fn task_count(&self) -> usize;
96}
97
98pub struct TaskManager {
104 tid_allocator: TidAllocator,
105 tasks: BTreeMap<u32, SharedTask>,
106}
107
108impl TaskManagerTrait for TaskManager {
109 fn new() -> Self {
110 TaskManager {
111 tid_allocator: TidAllocator::new(),
112 tasks: BTreeMap::new(),
113 }
114 }
115
116 fn allocate_tid(&mut self) -> u32 {
117 self.tid_allocator.allocate()
118 }
119
120 fn add_task(&mut self, task: SharedTask) {
121 let tid = task.lock().tid;
122 self.tasks.insert(tid, task);
123 }
124
125 fn exit_task(&mut self, task: SharedTask, code: i32) {
126 {
127 let mut task = task.lock();
128 task.exit_code = Some(code as i32);
129 }
130 exit_task_with_block(task);
131 }
132
133 fn release_task(&mut self, task: SharedTask) {
134 self.tasks.remove(&task.lock().tid);
135 }
136
137 fn get_task(&self, tid: u32) -> Option<SharedTask> {
138 self.tasks.get(&tid).cloned()
139 }
140
141 fn get_task_cond(&self, cond: impl Fn(&SharedTask) -> bool) -> Vec<SharedTask> {
142 let mut v = Vec::new();
143 for task in self.tasks.values() {
144 if cond(task) {
145 v.push(task.clone());
146 }
147 }
148 v
149 }
150
151 fn get_process_threads(&self, process: SharedTask) -> Vec<SharedTask> {
152 let mut v = Vec::new();
153 let pid = process.lock().pid;
154 for task in self.tasks.values() {
155 if task.lock().pid == pid {
156 v.push(task.clone());
157 }
158 }
159 v
160 }
161
162 fn get_process_children(&self, process: SharedTask) -> Vec<SharedTask> {
163 process.lock().children.lock().clone()
164 }
165
166 fn send_signal(&self, task: SharedTask, signal: usize) -> bool {
167 if let Some(signal_flag) = SignalFlags::from_signal_num(signal) {
168 let mut t = task.lock();
169 t.pending.signals.insert(signal_flag);
170 if t.state == TaskState::Interruptible {
171 drop(t);
172 wake_up_with_block(task.clone());
173 }
174 true
175 } else {
176 false
177 }
178 }
179
180 fn get_all_tasks(&self) -> Vec<SharedTask> {
181 self.tasks.values().cloned().collect()
182 }
183
184 #[cfg(test)]
185 fn task_count(&self) -> usize {
186 self.tasks.len()
187 }
188}
189
190#[cfg(test)]
191mod tests {
192 use alloc::sync::Arc;
193
194 use super::*;
195 use crate::{
196 kassert,
197 kernel::{TaskState, task::TaskStruct},
198 sync::SpinLock,
199 test_case,
200 };
201
202 fn new_dummy_task(tid: u32) -> SharedTask {
203 let task = TaskStruct::new_dummy_task(tid);
204 Arc::new(SpinLock::new(task))
205 }
206
207 test_case!(test_task_manager_allocate_sequence, {
209 let mut tm = TaskManager::new();
210 let t1 = tm.allocate_tid();
211 let t2 = tm.allocate_tid();
212 let t3 = tm.allocate_tid();
213 kassert!(t1 == 1);
214 kassert!(t2 == 2);
215 kassert!(t3 == 3);
216 });
217
218 test_case!(test_task_manager_get_remove_nonexistent, {
220 let mut tm = TaskManager::new();
221 kassert!(tm.get_task(42).is_none());
223
224 tm.exit_task(new_dummy_task(42), 0);
226 kassert!(tm.get_task(42).is_none());
227 });
228
229 test_case!(test_task_manager_add_get_exit, {
231 let mut tm = TaskManager::new();
232 let tid = tm.allocate_tid();
233 let task = new_dummy_task(tid);
234 tm.add_task(task.clone());
235 kassert!(tm.get_task(tid).is_some());
236
237 const EXIT_CODE: i32 = 42;
238
239 tm.exit_task(task, EXIT_CODE);
241
242 let exited_task = tm.get_task(tid).unwrap();
243 let g = exited_task.lock();
244
245 kassert!(g.exit_code == Some(EXIT_CODE as i32));
247
248 kassert!(g.state == TaskState::Zombie);
250 });
251
252 test_case!(test_task_manager_release_task, {
254 let mut tm = TaskManager::new();
255 let tid = tm.allocate_tid();
256 let task = new_dummy_task(tid);
257 tm.add_task(task.clone());
258
259 tm.exit_task(task.clone(), 0);
261 kassert!(tm.task_count() == 1);
262
263 tm.release_task(task);
265 kassert!(tm.task_count() == 0);
266 kassert!(tm.get_task(tid).is_none());
267 });
268}