From 84b10893d469028d8a21f2ce9de947626ab4b7e4 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Fri, 11 Dec 2020 16:14:14 +0800 Subject: [PATCH] forktree worked with depth=3 on k210 platform. --- os/src/mm/memory_set.rs | 2 +- os/src/syscall/fs.rs | 4 ++-- os/src/task/mod.rs | 24 ++++++++++++++---------- user/src/bin/forktest2.rs | 2 +- user/src/bin/forktree.rs | 37 +++++++++++++++++++++++++++++++++++++ user/src/bin/initproc.rs | 10 +++++++--- 6 files changed, 62 insertions(+), 17 deletions(-) create mode 100644 user/src/bin/forktree.rs diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs index 766c7594..9dce433f 100644 --- a/os/src/mm/memory_set.rs +++ b/os/src/mm/memory_set.rs @@ -212,7 +212,7 @@ impl MemorySet { pub fn translate(&self, vpn: VirtPageNum) -> Option { self.page_table.translate(vpn) } - pub fn clear(&mut self) { + pub fn recycle_data_pages(&mut self) { //*self = Self::new_bare(); self.areas.clear(); } diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index 39ef5f48..a10b53e9 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -1,5 +1,5 @@ use crate::mm::translated_byte_buffer; -use crate::task::{current_user_token}; +use crate::task::{current_user_token, suspend_current_and_run_next}; use crate::sbi::console_getchar; const FD_STDIN: usize = 0; @@ -28,7 +28,7 @@ pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize { loop { c = console_getchar(); if c == 0 { - //suspend_current_and_run_next(); + suspend_current_and_run_next(); continue; } else { break; diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index cebcb3b2..1a74b4f1 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -10,6 +10,7 @@ use switch::__switch; use task::{TaskControlBlock, TaskStatus}; use alloc::sync::Arc; use manager::fetch_task; +use lazy_static::*; pub use context::TaskContext; pub use processor::{ @@ -51,22 +52,20 @@ pub fn exit_current_and_run_next(exit_code: i32) { inner.task_status = TaskStatus::Zombie; // Record exit code inner.exit_code = exit_code; - // move any child to its parent - // TODO: do not move to its parent but under initproc + // do not move to its parent but under initproc - // ++++++ hold parent PCB lock here + // ++++++ hold initproc PCB lock here { - let parent = inner.parent.as_ref().unwrap().upgrade().unwrap(); - let mut parent_inner = parent.acquire_inner_lock(); + let mut initproc_inner = INITPROC.acquire_inner_lock(); for child in inner.children.iter() { - parent_inner.children.push(child.clone()); + initproc_inner.children.push(child.clone()); } } // ++++++ release parent PCB lock here inner.children.clear(); // deallocate user space - inner.memory_set.clear(); + inner.memory_set.recycle_data_pages(); drop(inner); // **** release current PCB lock // drop task manually to maintain rc correctly @@ -76,7 +75,12 @@ pub fn exit_current_and_run_next(exit_code: i32) { schedule(&_unused as *const _); } -pub fn add_initproc() { - let data = get_app_data_by_name("initproc").unwrap(); - add_task(Arc::new(TaskControlBlock::new(data))); +lazy_static! { + pub static ref INITPROC: Arc = Arc::new( + TaskControlBlock::new(get_app_data_by_name("initproc").unwrap()) + ); +} + +pub fn add_initproc() { + add_task(INITPROC.clone()); } diff --git a/user/src/bin/forktest2.rs b/user/src/bin/forktest2.rs index 95d5ca75..f47e73f2 100644 --- a/user/src/bin/forktest2.rs +++ b/user/src/bin/forktest2.rs @@ -30,6 +30,6 @@ pub fn main() -> i32 { assert_eq!(xstate, 0); } assert!(wait(&mut xstate) < 0); - println!("r_forktest2 test passed!"); + println!("forktest2 test passed!"); 0 } \ No newline at end of file diff --git a/user/src/bin/forktree.rs b/user/src/bin/forktree.rs new file mode 100644 index 00000000..397e5e05 --- /dev/null +++ b/user/src/bin/forktree.rs @@ -0,0 +1,37 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use user_lib::{sleep, getpid, fork, exit, yield_}; + +const DEPTH: usize = 3; + +fn fork_child(cur: &str, branch: char) { + let mut next = [0u8; DEPTH + 1]; + let l = cur.len(); + if l >= DEPTH { + return; + } + &mut next[..l].copy_from_slice(cur.as_bytes()); + next[l] = branch as u8; + if fork() == 0 { + fork_tree(core::str::from_utf8(&next[..l + 1]).unwrap()); + yield_(); + exit(0); + } +} + +fn fork_tree(cur: &str) { + println!("pid{}: {}", getpid(), cur); + fork_child(cur, '0'); + fork_child(cur, '1'); +} + +#[no_mangle] +pub fn main() -> i32 { + fork_tree(""); + sleep(3000); + 0 +} diff --git a/user/src/bin/initproc.rs b/user/src/bin/initproc.rs index 2ceb8488..6d30fdb6 100644 --- a/user/src/bin/initproc.rs +++ b/user/src/bin/initproc.rs @@ -17,13 +17,17 @@ fn main() -> i32 { exec("user_shell\0"); } else { loop { - let mut xstatus: i32 = 0; - let pid = wait(&mut xstatus); + let mut exit_code: i32 = 0; + let pid = wait(&mut exit_code); if pid == -1 { yield_(); continue; } - println!("[initproc] Release a zombie process!"); + println!( + "[initproc] Released a zombie process, pid={}, exit_code={}", + pid, + exit_code, + ); } } 0