From 4cfdce3362dac753c00b877b10c662567bfb4112 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Mon, 4 Apr 2022 21:03:35 +0800 Subject: [PATCH] update runtime info --- os/src/mm/frame_allocator.rs | 2 ++ os/src/syscall/process.rs | 3 ++ os/src/task/id.rs | 6 ++++ os/src/task/mod.rs | 16 ++++++++-- os/src/task/process.rs | 62 ++++++++++++++++++++---------------- os/src/task/task.rs | 6 ++-- user/src/lib.rs | 5 ++- 7 files changed, 66 insertions(+), 34 deletions(-) diff --git a/os/src/mm/frame_allocator.rs b/os/src/mm/frame_allocator.rs index 86b22d39..a4602d2d 100644 --- a/os/src/mm/frame_allocator.rs +++ b/os/src/mm/frame_allocator.rs @@ -28,7 +28,9 @@ impl Debug for FrameTracker { impl Drop for FrameTracker { fn drop(&mut self) { + kprintln!("[KERN] mm::frame_allocator::Drop::drop begin"); frame_dealloc(self.ppn); + kprintln!("[KERN] mm::frame_allocator::Drop::drop end"); } } diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index 51020c1d..e54a9e8c 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -96,14 +96,17 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize { // ++++ release child PCB }); if let Some((idx, _)) = pair { + kprintln!("[KERN] syscall::process::sys_waitpid(): remove child from PCB's children Vector"); let child = inner.children.remove(idx); // confirm that child will be deallocated after being removed from children list assert_eq!(Arc::strong_count(&child), 1); let found_pid = child.getpid(); // ++++ temporarily access child PCB exclusively + kprintln!("[KERN] syscall::process::sys_waitpid(): get child's exit_code and return child pid"); let exit_code = child.inner_exclusive_access().exit_code; // ++++ release child PCB *translated_refmut(inner.memory_set.token(), exit_code_ptr) = exit_code; + kprintln!("[KERN] syscall::process::sys_waitpid(): release child PCB"); found_pid as isize } else { -2 diff --git a/os/src/task/id.rs b/os/src/task/id.rs index 4eec31ed..912a96d5 100644 --- a/os/src/task/id.rs +++ b/os/src/task/id.rs @@ -61,7 +61,9 @@ pub fn pid_alloc() -> PidHandle { impl Drop for PidHandle { fn drop(&mut self) { + kprintln!("[KERN] task::id::Drop::drop begin"); PID_ALLOCATOR.exclusive_access().dealloc(self.0); + kprintln!("[KERN] task::id::Drop::drop end"); } } @@ -91,11 +93,13 @@ pub fn kstack_alloc() -> KernelStack { impl Drop for KernelStack { fn drop(&mut self) { + kprintln!("[KERN] task::id::Drop::drop begin"); let (kernel_stack_bottom, _) = kernel_stack_position(self.0); let kernel_stack_bottom_va: VirtAddr = kernel_stack_bottom.into(); KERNEL_SPACE .exclusive_access() .remove_area_with_start_vpn(kernel_stack_bottom_va.into()); + kprintln!("[KERN] task::id::Drop::drop end"); } } @@ -240,7 +244,9 @@ impl TaskUserRes { impl Drop for TaskUserRes { fn drop(&mut self) { + kprintln!("[KERN] task::id::Drop::drop begin"); self.dealloc_tid(); self.dealloc_user_res(); + kprintln!("[KERN] task::id::Drop::drop end"); } } diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 64bbc852..bc8c744c 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -67,24 +67,32 @@ pub fn exit_current_and_run_next(exit_code: i32) { let process = task.process.upgrade().unwrap(); let tid = task_inner.res.as_ref().unwrap().tid; // record exit code + 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; // here we do not remove the thread since we are still using the kstack // it will be deallocated when sys_waittid is called + 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); // however, if this is the main thread of current process // the process should terminate at once 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(); // mark this process as a zombie process + kprintln!("[KERN] task::exit_current_and_run_next(): mark this process as a zombie process"); process_inner.is_zombie = true; // record exit code of main process + kprintln!("[KERN] task::exit_current_and_run_next(): record exit code in process_inner"); process_inner.exit_code = exit_code; { // move all child processes under init process + 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)); @@ -95,22 +103,26 @@ pub fn exit_current_and_run_next(exit_code: i32) { // deallocate user res (including tid/trap_cx/ustack) of all threads // it has to be done before we dealloc the whole memory_set // otherwise they will be deallocated twice + 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(); // deallocate other data in user space i.e. program code/data section + kprintln!("[KERN] task::exit_current_and_run_next(): deallocate code/data in user space"); process_inner.memory_set.recycle_data_pages(); // drop file descriptors + 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); // we do not have to save task context let mut _unused = TaskContext::zero_init(); - kprintln!("[KERN] task::exit_current_and_run_next() end"); + kprintln!("[KERN] task::exit_current_and_run_next() end, sched next task"); schedule(&mut _unused as *mut _); } diff --git a/os/src/task/process.rs b/os/src/task/process.rs index 08ca3104..a64c88bb 100644 --- a/os/src/task/process.rs +++ b/os/src/task/process.rs @@ -72,14 +72,14 @@ impl ProcessControlBlock { } pub fn new(elf_data: &[u8]) -> Arc { - // memory_set with elf program headers/trampoline/trap context/user stack - kprintln!("[KERN] task::process::new() begin"); - kprintln!("[KERN] task::process::new(): build MemorySet, set user_stack_base, set entry_point"); + // memory_set with elf program headers/trampoline/user stack_base addr/entry_point + kprintln!("[KERN] task::process::PCB::new() begin"); + kprintln!("[KERN] task::process::PCB::new(): build MemorySet, set trampoline, user_stack_base, entry_point..."); let (memory_set, ustack_base, entry_point) = MemorySet::from_elf(elf_data); // allocate a pid - kprintln!("[KERN] task::process::new(): allocate a pid"); + kprintln!("[KERN] task::process::PCB::new(): allocate a pid"); let pid_handle = pid_alloc(); - kprintln!("[KERN] task::process::new(): new ProcessControlBlockInner"); + kprintln!("[KERN] task::process::PCB::new(): new ProcessControlBlockInner"); let process = Arc::new(Self { pid: pid_handle, inner: unsafe { @@ -107,15 +107,15 @@ impl ProcessControlBlock { }, }); // create a main thread, we should allocate ustack and trap_cx here - kprintln!("[KERN] task::process::new(): create a main thread begin"); - kprintln!("[KERN] task::process::new(): create a main thread: new TCB(alloc kstack, utack & trap_cx...) "); + kprintln!("[KERN] task::process::PCB::new(): create a main thread... start"); + kprintln!("[KERN] task::process::PCB::new(): create a main thread: new TCB(alloc kstack, utack & trap_cx...) "); let task = Arc::new(TaskControlBlock::new( Arc::clone(&process), ustack_base, true, )); // prepare trap_cx of main thread - kprintln!("[KERN] task::process::new(): create a main thread: set trap_cx(entry_point, ustack_top, k_satp, k_sp, trap_handler) "); + kprintln!("[KERN] task::process::PCB::new(): create a main thread: set trap_cx(entry_point, ustack_top, k_satp, k_sp, trap_handler) "); let task_inner = task.inner_exclusive_access(); let trap_cx = task_inner.get_trap_cx(); let ustack_top = task_inner.res.as_ref().unwrap().ustack_top(); @@ -128,38 +128,43 @@ impl ProcessControlBlock { kstack_top, trap_handler as usize, ); - kprintln!("[KERN] task::process::new(): create a main thread end"); + kprintln!("[KERN] task::process::PCB::new(): create a main thread... done"); // add main thread to the process - kprintln!("[KERN] task::process::new(): add main thread to the process"); + kprintln!("[KERN] task::process::PCB::new(): add main thread to the process"); let mut process_inner = process.inner_exclusive_access(); process_inner.tasks.push(Some(Arc::clone(&task))); drop(process_inner); - kprintln!("[KERN] task::process::new(): insert in PID2PCB BTreeMap"); + kprintln!("[KERN] task::process::PCB::new(): insert in PID2PCB BTreeMap"); insert_into_pid2process(process.getpid(), Arc::clone(&process)); // add main thread to scheduler - kprintln!("[KERN] task::process::new(): add_task(task): add main thread to scheduler"); + kprintln!("[KERN] task::process::PCB::new(): add_task(task): add main thread to scheduler"); add_task(task); - kprintln!("[KERN] task::process::new() end"); + kprintln!("[KERN] task::process::PCB::new() end"); process } /// Only support processes with a single thread. pub fn exec(self: &Arc, elf_data: &[u8], args: Vec) { + kprintln!("[KERN] task::process::PCB::exec() begin"); assert_eq!(self.inner_exclusive_access().thread_count(), 1); - // memory_set with elf program headers/trampoline/trap context/user stack - kprintln!("[KERN] task::process::exec() begin"); + // memory_set with elf program headers/trampoline/user_stack_base addr/entry_point + kprintln!("[KERN] task::process::PCB::exec(): build MemorySet, trampoline, user_stack_base, entry_point..."); let (memory_set, ustack_base, entry_point) = MemorySet::from_elf(elf_data); let new_token = memory_set.token(); // substitute memory_set + kprintln!("[KERN] task::process::PCB::exec(): substitute memory_set, ustack_base"); self.inner_exclusive_access().memory_set = memory_set; // then we alloc user resource for main thread again // since memory_set has been changed let task = self.inner_exclusive_access().get_task(0); let mut task_inner = task.inner_exclusive_access(); task_inner.res.as_mut().unwrap().ustack_base = ustack_base; + kprintln!("[KERN] task::process::PCB::exec(): alloc user resource for this thread"); task_inner.res.as_mut().unwrap().alloc_user_res(); + kprintln!("[KERN] task::process::PCB::exec(): set trap_cx_ppn for this thread"); task_inner.trap_cx_ppn = task_inner.res.as_mut().unwrap().trap_cx_ppn(); // push arguments on user stack + kprintln!("[KERN] task::process::PCB::exec(): push arguments on user stack for this thread"); let mut user_sp = task_inner.res.as_mut().unwrap().ustack_top(); user_sp -= (args.len() + 1) * core::mem::size_of::(); let argv_base = user_sp; @@ -185,6 +190,7 @@ impl ProcessControlBlock { // make the user_sp aligned to 8B for k210 platform user_sp -= user_sp % core::mem::size_of::(); // initialize trap_cx + kprintln!("[KERN] task::process::PCB::exec(): set trap_cx(entry_point, ustack_top, k_satp, k_sp, trap_handler, argc=x[10], argv=x[11])"); let mut trap_cx = TrapContext::app_init_context( entry_point, user_sp, @@ -195,22 +201,22 @@ impl ProcessControlBlock { trap_cx.x[10] = args.len(); trap_cx.x[11] = argv_base; *task_inner.get_trap_cx() = trap_cx; - kprintln!("[KERN] task::process::exec() end"); + kprintln!("[KERN] task::process::PCB::exec() end"); } /// Only support processes with a single thread. pub fn fork(self: &Arc) -> Arc { - kprintln!("[KERN] task::process::fork() begin"); + kprintln!("[KERN] task::process::PCB::fork() begin"); let mut parent = self.inner_exclusive_access(); assert_eq!(parent.thread_count(), 1); // clone parent's memory_set completely including trampoline/ustacks/trap_cxs - kprintln!("[KERN] task::process::fork(): clone parent's memory_set for child"); + kprintln!("[KERN] task::process::PCB::fork(): clone parent's memory_set for child"); let memory_set = MemorySet::from_existed_user(&parent.memory_set); // alloc a pid - kprintln!("[KERN] task::process::fork(): alloc a new pid for child"); + kprintln!("[KERN] task::process::PCB::fork(): alloc a new pid for child"); let pid = pid_alloc(); // copy fd table - kprintln!("[KERN] task::process::fork(): copy fd table for child"); + kprintln!("[KERN] task::process::PCB::fork(): copy fd table for child"); let mut new_fd_table: Vec>> = Vec::new(); for fd in parent.fd_table.iter() { if let Some(file) = fd { @@ -220,7 +226,7 @@ impl ProcessControlBlock { } } // create child process pcb - kprintln!("[KERN] task::process::fork(): new child PCB with new pid, memory_set, fd_table, ..."); + kprintln!("[KERN] task::process::PCB::fork(): new child PCB with new pid, memory_set, fd_table, ..."); let child = Arc::new(Self { pid, inner: unsafe { @@ -241,10 +247,10 @@ impl ProcessControlBlock { }, }); // add child - kprintln!("[KERN] task::process::fork(): add child link in parent' children Vec"); + kprintln!("[KERN] task::process::PCB::fork(): add child link in parent' children Vec"); parent.children.push(Arc::clone(&child)); // create main thread of child process - kprintln!("[KERN] task::process::fork(): TaskControlBlock::new(): create main thread of child process"); + kprintln!("[KERN] task::process::PCB::fork(): TaskControlBlock::new(): create main thread of child process"); let task = Arc::new(TaskControlBlock::new( Arc::clone(&child), parent @@ -259,22 +265,22 @@ impl ProcessControlBlock { false, )); // attach task to child process - kprintln!("[KERN] task::process::fork(): attach child TCB to child PCB"); + kprintln!("[KERN] task::process::PCB::fork(): attach child TCB to child PCB"); let mut child_inner = child.inner_exclusive_access(); child_inner.tasks.push(Some(Arc::clone(&task))); drop(child_inner); // modify kstack_top in trap_cx of this thread - kprintln!("[KERN] task::process::fork(): modify child's kstack_top in trap_cx of child"); + kprintln!("[KERN] task::process::PCB::fork(): modify child's kstack_top in trap_cx of child"); let task_inner = task.inner_exclusive_access(); let trap_cx = task_inner.get_trap_cx(); trap_cx.kernel_sp = task.kstack.get_top(); drop(task_inner); - kprintln!("[KERN] task::process::fork(): insert in PID2PCB BTreeMap"); + kprintln!("[KERN] task::process::PCB::fork(): insert in PID2PCB BTreeMap"); insert_into_pid2process(child.getpid(), Arc::clone(&child)); // add this thread to scheduler - kprintln!("[KERN] task::process::fork(): add_task(child task): add child thread to scheduler"); + kprintln!("[KERN] task::process::PCB::fork(): add_task(child task): add child thread to scheduler"); add_task(task); - kprintln!("[KERN] task::process::fork() end"); + kprintln!("[KERN] task::process::PCB::fork() end"); child } diff --git a/os/src/task/task.rs b/os/src/task/task.rs index b01f68bf..64550d99 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -49,13 +49,13 @@ impl TaskControlBlock { ustack_base: usize, alloc_user_res: bool, ) -> Self { - kprintln!("[KERN] TaskControlBlock::new() begin"); + kprintln!("[KERN] task::task::TaskControlBlock::new() begin"); let res = TaskUserRes::new(Arc::clone(&process), ustack_base, alloc_user_res); let trap_cx_ppn = res.trap_cx_ppn(); - kprintln!("[KERN] TaskControlBlock::new(): alloc kernel stack for TCB"); + kprintln!("[KERN] task::task::TaskControlBlock::new(): alloc kernel stack for TCB"); let kstack = kstack_alloc(); let kstack_top = kstack.get_top(); - kprintln!("[KERN] TaskControlBlock::new() end"); + kprintln!("[KERN] task::task::TaskControlBlock::new() end"); Self { process: Arc::downgrade(&process), kstack, diff --git a/user/src/lib.rs b/user/src/lib.rs index 60f39ffb..8f6e31b9 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -117,13 +117,16 @@ pub fn wait(exit_code: &mut i32) -> isize { } pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize { + println!("[USER] lib::waitpid() begin"); loop { match sys_waitpid(pid as isize, exit_code as *mut _) { -2 => { yield_(); } // -1 or a real pid - exit_pid => return exit_pid, + exit_pid => { + println!("[USER] lib::waitpid() end: exit_pid {}", exit_pid); + return exit_pid; } } } }