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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
mod context;
mod id;
mod manager;
mod process;
mod processor;
mod signal;
mod switch;
#[allow(clippy::module_inception)]
mod task;
use crate::fs::{open_file, OpenFlags};
use alloc::sync::Arc;
use lazy_static::*;
use manager::fetch_task;
use process::ProcessControlBlock;
use switch::__switch;
pub use context::TaskContext;
pub use id::{kstack_alloc, pid_alloc, KernelStack, PidHandle};
pub use manager::{add_task, pid2process, remove_from_pid2process};
pub use processor::{
current_kstack_top, current_process, current_task, current_trap_cx, current_trap_cx_user_va,
current_user_token, run_tasks, schedule, take_current_task,
};
pub use signal::SignalFlags;
pub use task::{TaskControlBlock, TaskStatus};
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 fn block_current_task() -> *mut TaskContext {
let task = take_current_task().unwrap();
let mut task_inner = task.inner_exclusive_access();
task_inner.task_status = TaskStatus::Blocking;
&mut task_inner.task_cx as *mut TaskContext
}
pub fn block_current_and_run_next() {
let task_cx_ptr = block_current_task();
schedule(task_cx_ptr);
}
pub fn exit_current_and_run_next(exit_code: i32) {
kprintln!("[KERN] task::exit_current_and_run_next() begin");
let task = take_current_task().unwrap();
let mut task_inner = task.inner_exclusive_access();
let process = task.process.upgrade().unwrap();
let tid = task_inner.res.as_ref().unwrap().tid;
kprintln!("[KERN] task::exit_current_and_run_next(): record exit code in task_inner");
task_inner.exit_code = Some(exit_code);
kprintln!("[KERN] task::exit_current_and_run_next(): TaskUserRes =>None");
task_inner.res = None;
kprintln!("[KERN] task::exit_current_and_run_next(): drop task_inner");
drop(task_inner);
kprintln!("[KERN] task::exit_current_and_run_next(): drop task");
drop(task);
if tid == 0 {
kprintln!("[KERN] task::exit_current_and_run_next(): it's main thread, process should terminate at once");
remove_from_pid2process(process.getpid());
let mut process_inner = process.inner_exclusive_access();
kprintln!("[KERN] task::exit_current_and_run_next(): mark this process as a zombie process");
process_inner.is_zombie = true;
kprintln!("[KERN] task::exit_current_and_run_next(): record exit code in process_inner");
process_inner.exit_code = exit_code;
{
kprintln!("[KERN] task::exit_current_and_run_next(): move all child processes under INITPROC");
let mut initproc_inner = INITPROC.inner_exclusive_access();
for child in process_inner.children.iter() {
child.inner_exclusive_access().parent = Some(Arc::downgrade(&INITPROC));
initproc_inner.children.push(child.clone());
}
}
kprintln!("[KERN] task::exit_current_and_run_next(): deallocate user res (tid/trap_cx/ustack) of all threads");
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;
}
kprintln!("[KERN] task::exit_current_and_run_next(): clear children Vector in process_inner");
process_inner.children.clear();
kprintln!("[KERN] task::exit_current_and_run_next(): deallocate code/data in user space");
process_inner.memory_set.recycle_data_pages();
kprintln!("[KERN] task::exit_current_and_run_next(): drop file descriptors");
process_inner.fd_table.clear();
}
kprintln!("[KERN] task::exit_current_and_run_next(): drop process");
drop(process);
let mut _unused = TaskContext::zero_init();
kprintln!("[KERN] task::exit_current_and_run_next() end, sched next task");
schedule(&mut _unused as *mut _);
}
lazy_static! {
pub static ref INITPROC: Arc<ProcessControlBlock> = {
kprintln!("[KERN] task::lazy_static!INITPROC begin");
let inode = open_file("initproc", OpenFlags::RDONLY).unwrap();
let v = inode.read_all();
ProcessControlBlock::new(v.as_slice())
};
}
pub fn add_initproc() {
kprintln!("[KERN] task::add_initproc() begin");
let _initproc = INITPROC.clone();
kprintln!("[KERN] task::add_initproc() end");
}
pub fn check_signals_of_current() -> Option<(i32, &'static str)> {
let process = current_process();
let process_inner = process.inner_exclusive_access();
process_inner.signals.check_error()
}
pub fn current_add_signal(signal: SignalFlags) {
let process = current_process();
let mut process_inner = process.inner_exclusive_access();
process_inner.signals |= signal;
}