1mod context;
18mod manager;
19mod pid;
20mod processor;
21mod switch;
22#[allow(clippy::module_inception)]
23#[allow(rustdoc::private_intra_doc_links)]
24mod task;
25
26use crate::fs::{OpenFlags, open_file};
27use crate::sbi::shutdown;
28use alloc::sync::Arc;
29pub use context::TaskContext;
30use lazy_static::*;
31pub use manager::{TaskManager, fetch_task};
32use switch::__switch;
33use task::{TaskControlBlock, TaskStatus};
34
35pub use manager::add_task;
36pub use pid::{KernelStack, PidAllocator, PidHandle, pid_alloc};
37pub use processor::{
38 Processor, current_task, current_trap_cx, current_user_token, run_tasks, schedule,
39 take_current_task,
40};
41pub fn suspend_current_and_run_next() {
43 let task = take_current_task().unwrap();
45
46 let mut task_inner = task.inner_exclusive_access();
48 let task_cx_ptr = &mut task_inner.task_cx as *mut TaskContext;
49 task_inner.task_status = TaskStatus::Ready;
51 drop(task_inner);
52 add_task(task);
56 schedule(task_cx_ptr);
58}
59
60pub const IDLE_PID: usize = 1;
62
63pub fn exit_current_and_run_next(exit_code: i32) {
65 let task = take_current_task().unwrap();
67
68 let pid = task.getpid();
69 if pid == IDLE_PID {
70 println!(
71 "[kernel] Idle process exit with exit_code {} ...",
72 exit_code
73 );
74 if exit_code != 0 {
75 shutdown(true)
77 } else {
78 shutdown(false)
80 }
81 }
82
83 let mut inner = task.inner_exclusive_access();
85 inner.task_status = TaskStatus::Zombie;
87 inner.exit_code = exit_code;
89 {
93 let mut initproc_inner = INITPROC.inner_exclusive_access();
94 for child in inner.children.iter() {
95 child.inner_exclusive_access().parent = Some(Arc::downgrade(&INITPROC));
96 initproc_inner.children.push(child.clone());
97 }
98 }
99 inner.children.clear();
102 inner.memory_set.recycle_data_pages();
104 drop(inner);
105 drop(task);
108 let mut _unused = TaskContext::zero_init();
110 schedule(&mut _unused as *mut _);
111}
112
113lazy_static! {
114 pub static ref INITPROC: Arc<TaskControlBlock> = Arc::new({
116 let inode = open_file("initproc", OpenFlags::RDONLY).unwrap();
117 let v = inode.read_all();
118 TaskControlBlock::new(v.as_slice())
119 });
120}
121pub fn add_initproc() {
123 add_task(INITPROC.clone());
124}