1use super::TaskControlBlock;
2use super::id::RecycleAllocator;
3use super::manager::insert_into_pid2process;
4use super::{PidHandle, pid_alloc};
5use super::{SignalFlags, add_task};
6use crate::fs::{File, Stdin, Stdout};
7use crate::mm::{KERNEL_SPACE, MemorySet, translated_refmut};
8use crate::sync::{Condvar, Mutex, Semaphore, UPIntrFreeCell, UPIntrRefMut};
9use crate::trap::{TrapContext, trap_handler};
10use alloc::string::String;
11use alloc::sync::{Arc, Weak};
12use alloc::vec;
13use alloc::vec::Vec;
14
15pub struct ProcessControlBlock {
16 pub pid: PidHandle,
18 inner: UPIntrFreeCell<ProcessControlBlockInner>,
20}
21
22pub struct ProcessControlBlockInner {
23 pub is_zombie: bool,
24 pub memory_set: MemorySet,
25 pub parent: Option<Weak<ProcessControlBlock>>,
26 pub children: Vec<Arc<ProcessControlBlock>>,
27 pub exit_code: i32,
28 pub fd_table: Vec<Option<Arc<dyn File + Send + Sync>>>,
29 pub signals: SignalFlags,
30 pub tasks: Vec<Option<Arc<TaskControlBlock>>>,
31 pub task_res_allocator: RecycleAllocator,
32 pub mutex_list: Vec<Option<Arc<dyn Mutex>>>,
33 pub semaphore_list: Vec<Option<Arc<Semaphore>>>,
34 pub condvar_list: Vec<Option<Arc<Condvar>>>,
35}
36
37impl ProcessControlBlockInner {
38 #[allow(unused)]
39 pub fn get_user_token(&self) -> usize {
40 self.memory_set.token()
41 }
42
43 pub fn alloc_fd(&mut self) -> usize {
44 if let Some(fd) = (0..self.fd_table.len()).find(|fd| self.fd_table[*fd].is_none()) {
45 fd
46 } else {
47 self.fd_table.push(None);
48 self.fd_table.len() - 1
49 }
50 }
51
52 pub fn alloc_tid(&mut self) -> usize {
53 self.task_res_allocator.alloc()
54 }
55
56 pub fn dealloc_tid(&mut self, tid: usize) {
57 self.task_res_allocator.dealloc(tid)
58 }
59
60 pub fn thread_count(&self) -> usize {
61 self.tasks.len()
62 }
63
64 pub fn get_task(&self, tid: usize) -> Arc<TaskControlBlock> {
65 self.tasks[tid].as_ref().unwrap().clone()
66 }
67}
68
69impl ProcessControlBlock {
70 pub fn inner_exclusive_access(&self) -> UPIntrRefMut<'_, ProcessControlBlockInner> {
71 self.inner.exclusive_access()
72 }
73
74 pub fn new(elf_data: &[u8]) -> Arc<Self> {
75 let (memory_set, ustack_base, entry_point) = MemorySet::from_elf(elf_data);
77 let pid_handle = pid_alloc();
79 let process = Arc::new(Self {
80 pid: pid_handle,
81 inner: unsafe {
82 UPIntrFreeCell::new(ProcessControlBlockInner {
83 is_zombie: false,
84 memory_set,
85 parent: None,
86 children: Vec::new(),
87 exit_code: 0,
88 fd_table: vec![
89 Some(Arc::new(Stdin)),
91 Some(Arc::new(Stdout)),
93 Some(Arc::new(Stdout)),
95 ],
96 signals: SignalFlags::empty(),
97 tasks: Vec::new(),
98 task_res_allocator: RecycleAllocator::new(),
99 mutex_list: Vec::new(),
100 semaphore_list: Vec::new(),
101 condvar_list: Vec::new(),
102 })
103 },
104 });
105 let task = Arc::new(TaskControlBlock::new(
107 Arc::clone(&process),
108 ustack_base,
109 true,
110 ));
111 let task_inner = task.inner_exclusive_access();
113 let trap_cx = task_inner.get_trap_cx();
114 let ustack_top = task_inner.res.as_ref().unwrap().ustack_top();
115 let kstack_top = task.kstack.get_top();
116 drop(task_inner);
117 *trap_cx = TrapContext::app_init_context(
118 entry_point,
119 ustack_top,
120 KERNEL_SPACE.exclusive_access().token(),
121 kstack_top,
122 linker_symbol_addr!(trap_handler),
123 );
124 let mut process_inner = process.inner_exclusive_access();
126 process_inner.tasks.push(Some(Arc::clone(&task)));
127 drop(process_inner);
128 insert_into_pid2process(process.getpid(), Arc::clone(&process));
129 add_task(task);
131 process
132 }
133
134 pub fn exec(self: &Arc<Self>, elf_data: &[u8], args: Vec<String>) {
136 assert_eq!(self.inner_exclusive_access().thread_count(), 1);
137 let (memory_set, ustack_base, entry_point) = MemorySet::from_elf(elf_data);
139 let new_token = memory_set.token();
140 self.inner_exclusive_access().memory_set = memory_set;
142 let task = self.inner_exclusive_access().get_task(0);
145 let mut task_inner = task.inner_exclusive_access();
146 task_inner.res.as_mut().unwrap().ustack_base = ustack_base;
147 task_inner.res.as_mut().unwrap().alloc_user_res();
148 task_inner.trap_cx_ppn = task_inner.res.as_mut().unwrap().trap_cx_ppn();
149 let mut user_sp = task_inner.res.as_mut().unwrap().ustack_top();
151 user_sp -= (args.len() + 1) * core::mem::size_of::<usize>();
152 let argv_base = user_sp;
153 let mut argv: Vec<_> = (0..=args.len())
154 .map(|arg| {
155 translated_refmut(
156 new_token,
157 (argv_base + arg * core::mem::size_of::<usize>()) as *mut usize,
158 )
159 })
160 .collect();
161 *argv[args.len()] = 0;
162 for i in 0..args.len() {
163 user_sp -= args[i].len() + 1;
164 *argv[i] = user_sp;
165 let mut p = user_sp;
166 for c in args[i].as_bytes() {
167 *translated_refmut(new_token, p as *mut u8) = *c;
168 p += 1;
169 }
170 *translated_refmut(new_token, p as *mut u8) = 0;
171 }
172 user_sp -= user_sp % core::mem::size_of::<usize>();
174 let mut trap_cx = TrapContext::app_init_context(
176 entry_point,
177 user_sp,
178 KERNEL_SPACE.exclusive_access().token(),
179 task.kstack.get_top(),
180 linker_symbol_addr!(trap_handler),
181 );
182 trap_cx.x[10] = args.len();
183 trap_cx.x[11] = argv_base;
184 *task_inner.get_trap_cx() = trap_cx;
185 }
186
187 pub fn fork(self: &Arc<Self>) -> Arc<Self> {
189 let mut parent = self.inner_exclusive_access();
190 assert_eq!(parent.thread_count(), 1);
191 let memory_set = MemorySet::from_existed_user(&parent.memory_set);
193 let pid = pid_alloc();
195 let mut new_fd_table: Vec<Option<Arc<dyn File + Send + Sync>>> = Vec::new();
197 for fd in parent.fd_table.iter() {
198 if let Some(file) = fd {
199 new_fd_table.push(Some(file.clone()));
200 } else {
201 new_fd_table.push(None);
202 }
203 }
204 let child = Arc::new(Self {
206 pid,
207 inner: unsafe {
208 UPIntrFreeCell::new(ProcessControlBlockInner {
209 is_zombie: false,
210 memory_set,
211 parent: Some(Arc::downgrade(self)),
212 children: Vec::new(),
213 exit_code: 0,
214 fd_table: new_fd_table,
215 signals: SignalFlags::empty(),
216 tasks: Vec::new(),
217 task_res_allocator: RecycleAllocator::new(),
218 mutex_list: Vec::new(),
219 semaphore_list: Vec::new(),
220 condvar_list: Vec::new(),
221 })
222 },
223 });
224 parent.children.push(Arc::clone(&child));
226 let task = Arc::new(TaskControlBlock::new(
228 Arc::clone(&child),
229 parent
230 .get_task(0)
231 .inner_exclusive_access()
232 .res
233 .as_ref()
234 .unwrap()
235 .ustack_base(),
236 false,
239 ));
240 let mut child_inner = child.inner_exclusive_access();
242 child_inner.tasks.push(Some(Arc::clone(&task)));
243 drop(child_inner);
244 let task_inner = task.inner_exclusive_access();
246 let trap_cx = task_inner.get_trap_cx();
247 trap_cx.kernel_sp = task.kstack.get_top();
248 drop(task_inner);
249 insert_into_pid2process(child.getpid(), Arc::clone(&child));
250 add_task(task);
252 child
253 }
254
255 pub fn getpid(&self) -> usize {
256 self.pid.0
257 }
258}