1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
mod context;
mod manager;
mod pid;
mod processor;
mod switch;
#[allow(clippy::module_inception)]
mod task;
use crate::loader::get_app_data_by_name;
use alloc::sync::Arc;
use lazy_static::*;
pub use manager::{fetch_task, TaskManager};
use switch::__switch;
use task::{TaskControlBlock, TaskStatus};
pub use context::TaskContext;
pub use manager::add_task;
pub use pid::{pid_alloc, KernelStack, PidAllocator, PidHandle};
pub use processor::{
current_task, current_trap_cx, current_user_token, run_tasks, schedule, take_current_task,
Processor,
};
pub fn suspend_current_and_run_next() {
let task = take_current_task().unwrap();
let mut task_inner = task.inner_exclusive_access();
let task_cx_ptr = &mut task_inner.task_cx as *mut TaskContext;
task_inner.task_status = TaskStatus::Ready;
drop(task_inner);
add_task(task);
schedule(task_cx_ptr);
}
pub const IDLE_PID: usize = 0;
#[cfg(feature = "board_qemu")]
use crate::board::QEMUExit;
pub fn exit_current_and_run_next(exit_code: i32) {
let task = take_current_task().unwrap();
#[cfg(feature = "board_qemu")]
let pid = task.getpid();
#[cfg(feature = "board_qemu")]
if pid == IDLE_PID {
println!(
"[kernel] Idle process exit with exit_code {} ...",
exit_code
);
if exit_code != 0 {
crate::board::QEMU_EXIT_HANDLE.exit_failure();
} else {
crate::board::QEMU_EXIT_HANDLE.exit_success();
}
}
let mut inner = task.inner_exclusive_access();
inner.task_status = TaskStatus::Zombie;
inner.exit_code = exit_code;
{
let mut initproc_inner = INITPROC.inner_exclusive_access();
for child in inner.children.iter() {
child.inner_exclusive_access().parent = Some(Arc::downgrade(&INITPROC));
initproc_inner.children.push(child.clone());
}
}
inner.children.clear();
inner.memory_set.recycle_data_pages();
drop(inner);
drop(task);
let mut _unused = TaskContext::zero_init();
schedule(&mut _unused as *mut _);
}
lazy_static! {
pub static ref INITPROC: Arc<TaskControlBlock> = Arc::new(TaskControlBlock::new(
get_app_data_by_name("initproc").unwrap()
));
}
pub fn add_initproc() {
add_task(INITPROC.clone());
}