update runtime info

This commit is contained in:
Yu Chen 2022-04-04 21:03:35 +08:00
parent e7084e4a96
commit 4cfdce3362
7 changed files with 66 additions and 34 deletions

View File

@ -28,7 +28,9 @@ impl Debug for FrameTracker {
impl Drop for FrameTracker { impl Drop for FrameTracker {
fn drop(&mut self) { fn drop(&mut self) {
kprintln!("[KERN] mm::frame_allocator::Drop<FrameTracker>::drop begin");
frame_dealloc(self.ppn); frame_dealloc(self.ppn);
kprintln!("[KERN] mm::frame_allocator::Drop<FrameTracker>::drop end");
} }
} }

View File

@ -96,14 +96,17 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
// ++++ release child PCB // ++++ release child PCB
}); });
if let Some((idx, _)) = pair { if let Some((idx, _)) = pair {
kprintln!("[KERN] syscall::process::sys_waitpid(): remove child from PCB's children Vector");
let child = inner.children.remove(idx); let child = inner.children.remove(idx);
// confirm that child will be deallocated after being removed from children list // confirm that child will be deallocated after being removed from children list
assert_eq!(Arc::strong_count(&child), 1); assert_eq!(Arc::strong_count(&child), 1);
let found_pid = child.getpid(); let found_pid = child.getpid();
// ++++ temporarily access child PCB exclusively // ++++ 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; let exit_code = child.inner_exclusive_access().exit_code;
// ++++ release child PCB // ++++ release child PCB
*translated_refmut(inner.memory_set.token(), exit_code_ptr) = exit_code; *translated_refmut(inner.memory_set.token(), exit_code_ptr) = exit_code;
kprintln!("[KERN] syscall::process::sys_waitpid(): release child PCB");
found_pid as isize found_pid as isize
} else { } else {
-2 -2

View File

@ -61,7 +61,9 @@ pub fn pid_alloc() -> PidHandle {
impl Drop for PidHandle { impl Drop for PidHandle {
fn drop(&mut self) { fn drop(&mut self) {
kprintln!("[KERN] task::id::Drop<PidHandle>::drop begin");
PID_ALLOCATOR.exclusive_access().dealloc(self.0); PID_ALLOCATOR.exclusive_access().dealloc(self.0);
kprintln!("[KERN] task::id::Drop<PidHandle>::drop end");
} }
} }
@ -91,11 +93,13 @@ pub fn kstack_alloc() -> KernelStack {
impl Drop for KernelStack { impl Drop for KernelStack {
fn drop(&mut self) { fn drop(&mut self) {
kprintln!("[KERN] task::id::Drop<KernelStack>::drop begin");
let (kernel_stack_bottom, _) = kernel_stack_position(self.0); let (kernel_stack_bottom, _) = kernel_stack_position(self.0);
let kernel_stack_bottom_va: VirtAddr = kernel_stack_bottom.into(); let kernel_stack_bottom_va: VirtAddr = kernel_stack_bottom.into();
KERNEL_SPACE KERNEL_SPACE
.exclusive_access() .exclusive_access()
.remove_area_with_start_vpn(kernel_stack_bottom_va.into()); .remove_area_with_start_vpn(kernel_stack_bottom_va.into());
kprintln!("[KERN] task::id::Drop<KernelStack>::drop end");
} }
} }
@ -240,7 +244,9 @@ impl TaskUserRes {
impl Drop for TaskUserRes { impl Drop for TaskUserRes {
fn drop(&mut self) { fn drop(&mut self) {
kprintln!("[KERN] task::id::Drop<TaskUserRes>::drop begin");
self.dealloc_tid(); self.dealloc_tid();
self.dealloc_user_res(); self.dealloc_user_res();
kprintln!("[KERN] task::id::Drop<TaskUserRes>::drop end");
} }
} }

View File

@ -67,24 +67,32 @@ pub fn exit_current_and_run_next(exit_code: i32) {
let process = task.process.upgrade().unwrap(); let process = task.process.upgrade().unwrap();
let tid = task_inner.res.as_ref().unwrap().tid; let tid = task_inner.res.as_ref().unwrap().tid;
// record exit code // record exit code
kprintln!("[KERN] task::exit_current_and_run_next(): record exit code in task_inner");
task_inner.exit_code = Some(exit_code); task_inner.exit_code = Some(exit_code);
kprintln!("[KERN] task::exit_current_and_run_next(): TaskUserRes =>None");
task_inner.res = None; task_inner.res = None;
// here we do not remove the thread since we are still using the kstack // here we do not remove the thread since we are still using the kstack
// it will be deallocated when sys_waittid is called // it will be deallocated when sys_waittid is called
kprintln!("[KERN] task::exit_current_and_run_next(): drop task_inner");
drop(task_inner); drop(task_inner);
kprintln!("[KERN] task::exit_current_and_run_next(): drop task");
drop(task); drop(task);
// however, if this is the main thread of current process // however, if this is the main thread of current process
// the process should terminate at once // the process should terminate at once
if tid == 0 { 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()); remove_from_pid2process(process.getpid());
let mut process_inner = process.inner_exclusive_access(); let mut process_inner = process.inner_exclusive_access();
// mark this process as a zombie process // 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; process_inner.is_zombie = true;
// record exit code of main process // 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; process_inner.exit_code = exit_code;
{ {
// move all child processes under init process // 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(); let mut initproc_inner = INITPROC.inner_exclusive_access();
for child in process_inner.children.iter() { for child in process_inner.children.iter() {
child.inner_exclusive_access().parent = Some(Arc::downgrade(&INITPROC)); 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 // deallocate user res (including tid/trap_cx/ustack) of all threads
// it has to be done before we dealloc the whole memory_set // it has to be done before we dealloc the whole memory_set
// otherwise they will be deallocated twice // 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()) { for task in process_inner.tasks.iter().filter(|t| t.is_some()) {
let task = task.as_ref().unwrap(); let task = task.as_ref().unwrap();
let mut task_inner = task.inner_exclusive_access(); let mut task_inner = task.inner_exclusive_access();
task_inner.res = None; task_inner.res = None;
} }
kprintln!("[KERN] task::exit_current_and_run_next(): clear children Vector in process_inner");
process_inner.children.clear(); process_inner.children.clear();
// deallocate other data in user space i.e. program code/data section // 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(); process_inner.memory_set.recycle_data_pages();
// drop file descriptors // drop file descriptors
kprintln!("[KERN] task::exit_current_and_run_next(): drop file descriptors");
process_inner.fd_table.clear(); process_inner.fd_table.clear();
} }
kprintln!("[KERN] task::exit_current_and_run_next(): drop process");
drop(process); drop(process);
// we do not have to save task context // we do not have to save task context
let mut _unused = TaskContext::zero_init(); 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 _); schedule(&mut _unused as *mut _);
} }

View File

@ -72,14 +72,14 @@ impl ProcessControlBlock {
} }
pub fn new(elf_data: &[u8]) -> Arc<Self> { pub fn new(elf_data: &[u8]) -> Arc<Self> {
// memory_set with elf program headers/trampoline/trap context/user stack // memory_set with elf program headers/trampoline/user stack_base addr/entry_point
kprintln!("[KERN] task::process::new() begin"); kprintln!("[KERN] task::process::PCB::new() begin");
kprintln!("[KERN] task::process::new(): build MemorySet, set user_stack_base, set entry_point"); 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); let (memory_set, ustack_base, entry_point) = MemorySet::from_elf(elf_data);
// allocate a pid // 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(); 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 { let process = Arc::new(Self {
pid: pid_handle, pid: pid_handle,
inner: unsafe { inner: unsafe {
@ -107,15 +107,15 @@ impl ProcessControlBlock {
}, },
}); });
// create a main thread, we should allocate ustack and trap_cx here // 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::PCB::new(): create a main thread... start");
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: new TCB(alloc kstack, utack & trap_cx...) ");
let task = Arc::new(TaskControlBlock::new( let task = Arc::new(TaskControlBlock::new(
Arc::clone(&process), Arc::clone(&process),
ustack_base, ustack_base,
true, true,
)); ));
// prepare trap_cx of main thread // 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 task_inner = task.inner_exclusive_access();
let trap_cx = task_inner.get_trap_cx(); let trap_cx = task_inner.get_trap_cx();
let ustack_top = task_inner.res.as_ref().unwrap().ustack_top(); let ustack_top = task_inner.res.as_ref().unwrap().ustack_top();
@ -128,38 +128,43 @@ impl ProcessControlBlock {
kstack_top, kstack_top,
trap_handler as usize, 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 // 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(); let mut process_inner = process.inner_exclusive_access();
process_inner.tasks.push(Some(Arc::clone(&task))); process_inner.tasks.push(Some(Arc::clone(&task)));
drop(process_inner); drop(process_inner);
kprintln!("[KERN] task::process::new(): insert <pid, PCB> in PID2PCB BTreeMap"); kprintln!("[KERN] task::process::PCB::new(): insert <pid, PCB> in PID2PCB BTreeMap");
insert_into_pid2process(process.getpid(), Arc::clone(&process)); insert_into_pid2process(process.getpid(), Arc::clone(&process));
// add main thread to scheduler // 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); add_task(task);
kprintln!("[KERN] task::process::new() end"); kprintln!("[KERN] task::process::PCB::new() end");
process process
} }
/// Only support processes with a single thread. /// Only support processes with a single thread.
pub fn exec(self: &Arc<Self>, elf_data: &[u8], args: Vec<String>) { pub fn exec(self: &Arc<Self>, elf_data: &[u8], args: Vec<String>) {
kprintln!("[KERN] task::process::PCB::exec() begin");
assert_eq!(self.inner_exclusive_access().thread_count(), 1); assert_eq!(self.inner_exclusive_access().thread_count(), 1);
// memory_set with elf program headers/trampoline/trap context/user stack // memory_set with elf program headers/trampoline/user_stack_base addr/entry_point
kprintln!("[KERN] task::process::exec() begin"); 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 (memory_set, ustack_base, entry_point) = MemorySet::from_elf(elf_data);
let new_token = memory_set.token(); let new_token = memory_set.token();
// substitute memory_set // substitute memory_set
kprintln!("[KERN] task::process::PCB::exec(): substitute memory_set, ustack_base");
self.inner_exclusive_access().memory_set = memory_set; self.inner_exclusive_access().memory_set = memory_set;
// then we alloc user resource for main thread again // then we alloc user resource for main thread again
// since memory_set has been changed // since memory_set has been changed
let task = self.inner_exclusive_access().get_task(0); let task = self.inner_exclusive_access().get_task(0);
let mut task_inner = task.inner_exclusive_access(); let mut task_inner = task.inner_exclusive_access();
task_inner.res.as_mut().unwrap().ustack_base = ustack_base; 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(); 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(); task_inner.trap_cx_ppn = task_inner.res.as_mut().unwrap().trap_cx_ppn();
// push arguments on user stack // 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(); let mut user_sp = task_inner.res.as_mut().unwrap().ustack_top();
user_sp -= (args.len() + 1) * core::mem::size_of::<usize>(); user_sp -= (args.len() + 1) * core::mem::size_of::<usize>();
let argv_base = user_sp; let argv_base = user_sp;
@ -185,6 +190,7 @@ impl ProcessControlBlock {
// make the user_sp aligned to 8B for k210 platform // make the user_sp aligned to 8B for k210 platform
user_sp -= user_sp % core::mem::size_of::<usize>(); user_sp -= user_sp % core::mem::size_of::<usize>();
// initialize trap_cx // 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( let mut trap_cx = TrapContext::app_init_context(
entry_point, entry_point,
user_sp, user_sp,
@ -195,22 +201,22 @@ impl ProcessControlBlock {
trap_cx.x[10] = args.len(); trap_cx.x[10] = args.len();
trap_cx.x[11] = argv_base; trap_cx.x[11] = argv_base;
*task_inner.get_trap_cx() = trap_cx; *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. /// Only support processes with a single thread.
pub fn fork(self: &Arc<Self>) -> Arc<Self> { pub fn fork(self: &Arc<Self>) -> Arc<Self> {
kprintln!("[KERN] task::process::fork() begin"); kprintln!("[KERN] task::process::PCB::fork() begin");
let mut parent = self.inner_exclusive_access(); let mut parent = self.inner_exclusive_access();
assert_eq!(parent.thread_count(), 1); assert_eq!(parent.thread_count(), 1);
// clone parent's memory_set completely including trampoline/ustacks/trap_cxs // 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); let memory_set = MemorySet::from_existed_user(&parent.memory_set);
// alloc a pid // 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(); let pid = pid_alloc();
// copy fd table // 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<Option<Arc<dyn File + Send + Sync>>> = Vec::new(); let mut new_fd_table: Vec<Option<Arc<dyn File + Send + Sync>>> = Vec::new();
for fd in parent.fd_table.iter() { for fd in parent.fd_table.iter() {
if let Some(file) = fd { if let Some(file) = fd {
@ -220,7 +226,7 @@ impl ProcessControlBlock {
} }
} }
// create child process pcb // 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 { let child = Arc::new(Self {
pid, pid,
inner: unsafe { inner: unsafe {
@ -241,10 +247,10 @@ impl ProcessControlBlock {
}, },
}); });
// add child // 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)); parent.children.push(Arc::clone(&child));
// create main thread of child process // 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( let task = Arc::new(TaskControlBlock::new(
Arc::clone(&child), Arc::clone(&child),
parent parent
@ -259,22 +265,22 @@ impl ProcessControlBlock {
false, false,
)); ));
// attach task to child process // 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(); let mut child_inner = child.inner_exclusive_access();
child_inner.tasks.push(Some(Arc::clone(&task))); child_inner.tasks.push(Some(Arc::clone(&task)));
drop(child_inner); drop(child_inner);
// modify kstack_top in trap_cx of this thread // 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 task_inner = task.inner_exclusive_access();
let trap_cx = task_inner.get_trap_cx(); let trap_cx = task_inner.get_trap_cx();
trap_cx.kernel_sp = task.kstack.get_top(); trap_cx.kernel_sp = task.kstack.get_top();
drop(task_inner); drop(task_inner);
kprintln!("[KERN] task::process::fork(): insert <child pid, child PCB> in PID2PCB BTreeMap"); kprintln!("[KERN] task::process::PCB::fork(): insert <child pid, child PCB> in PID2PCB BTreeMap");
insert_into_pid2process(child.getpid(), Arc::clone(&child)); insert_into_pid2process(child.getpid(), Arc::clone(&child));
// add this thread to scheduler // 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); add_task(task);
kprintln!("[KERN] task::process::fork() end"); kprintln!("[KERN] task::process::PCB::fork() end");
child child
} }

View File

@ -49,13 +49,13 @@ impl TaskControlBlock {
ustack_base: usize, ustack_base: usize,
alloc_user_res: bool, alloc_user_res: bool,
) -> Self { ) -> 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 res = TaskUserRes::new(Arc::clone(&process), ustack_base, alloc_user_res);
let trap_cx_ppn = res.trap_cx_ppn(); 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 = kstack_alloc();
let kstack_top = kstack.get_top(); let kstack_top = kstack.get_top();
kprintln!("[KERN] TaskControlBlock::new() end"); kprintln!("[KERN] task::task::TaskControlBlock::new() end");
Self { Self {
process: Arc::downgrade(&process), process: Arc::downgrade(&process),
kstack, kstack,

View File

@ -117,13 +117,16 @@ pub fn wait(exit_code: &mut i32) -> isize {
} }
pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize { pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize {
println!("[USER] lib::waitpid() begin");
loop { loop {
match sys_waitpid(pid as isize, exit_code as *mut _) { match sys_waitpid(pid as isize, exit_code as *mut _) {
-2 => { -2 => {
yield_(); yield_();
} }
// -1 or a real pid // -1 or a real pid
exit_pid => return exit_pid, exit_pid => {
println!("[USER] lib::waitpid() end: exit_pid {}", exit_pid);
return exit_pid; }
} }
} }
} }