Only support processes with a single thread.
(self: &Arc<Self>)
| 186 | |
| 187 | /// Only support processes with a single thread. |
| 188 | pub fn fork(self: &Arc<Self>) -> Arc<Self> { |
| 189 | let mut parent = self.inner_exclusive_access(); |
| 190 | assert_eq!(parent.thread_count(), 1); |
| 191 | // clone parent's memory_set completely including trampoline/ustacks/trap_cxs |
| 192 | let memory_set = MemorySet::from_existed_user(&parent.memory_set); |
| 193 | // alloc a pid |
| 194 | let pid = pid_alloc(); |
| 195 | // copy fd table |
| 196 | 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 | // create child process pcb |
| 205 | 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 | // add child |
| 225 | parent.children.push(Arc::clone(&child)); |
| 226 | // create main thread of child process |
| 227 | 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 | // here we do not allocate trap_cx or ustack again |
| 237 | // but mention that we allocate a new kstack here |
| 238 | false, |
| 239 | )); |
| 240 | // attach task to child process |
| 241 | let mut child_inner = child.inner_exclusive_access(); |
| 242 | child_inner.tasks.push(Some(Arc::clone(&task))); |
| 243 | drop(child_inner); |
| 244 | // modify kstack_top in trap_cx of this thread |
| 245 | let task_inner = task.inner_exclusive_access(); |
no test coverage detected