From 4d8d48cf4deb22d649b7c5c5336dc2461e1d1c2e Mon Sep 17 00:00:00 2001 From: chenqiuhao Date: Wed, 14 Nov 2018 18:36:47 +0800 Subject: [PATCH] repair some bugs and move child control to processmanager --- crate/process/src/interrupt.rs | 29 ++++++++++++++++++++++++++++ crate/process/src/lib.rs | 4 +++- crate/process/src/process_manager.rs | 16 ++++++++++++--- crate/process/src/processor.rs | 14 +++++++++++--- crate/process/src/thread.rs | 1 + crate/riscv | 2 +- kernel/src/fs.rs | 4 ++++ kernel/src/process/mod.rs | 26 ------------------------- kernel/src/sync/test.rs | 2 +- kernel/src/syscall.rs | 4 +--- 10 files changed, 64 insertions(+), 38 deletions(-) create mode 100644 crate/process/src/interrupt.rs diff --git a/crate/process/src/interrupt.rs b/crate/process/src/interrupt.rs new file mode 100644 index 0000000..f75102e --- /dev/null +++ b/crate/process/src/interrupt.rs @@ -0,0 +1,29 @@ +#[inline(always)] +#[cfg(target_arch = "x86_64")] +pub unsafe fn disable_and_store() -> usize { + let rflags: usize; + asm!("pushfq; popq $0; cli" : "=r"(rflags)); + rflags & (1 << 9) +} + +#[inline(always)] +#[cfg(target_arch = "riscv32")] +pub unsafe fn disable_and_store() -> usize { + let sstatus: usize; + asm!("csrrci $0, 0x100, 1" : "=r"(sstatus)); + sstatus & 1 +} + +#[inline(always)] +#[cfg(target_arch = "x86_64")] +pub unsafe fn restore(flags: usize) { + if flags != 0 { + asm!("sti"); + } +} + +#[inline(always)] +#[cfg(target_arch = "riscv32")] +pub unsafe fn restore(flags: usize) { + asm!("csrs 0x100, $0" :: "r"(flags)); +} \ No newline at end of file diff --git a/crate/process/src/lib.rs b/crate/process/src/lib.rs index d6e4c7d..d798459 100644 --- a/crate/process/src/lib.rs +++ b/crate/process/src/lib.rs @@ -4,6 +4,7 @@ #![feature(linkage)] #![feature(nll)] #![feature(vec_resize_default)] +#![feature(asm)] #![feature(exact_size_is_empty)] extern crate alloc; @@ -16,11 +17,12 @@ extern crate spin; #[macro_use] extern crate std; -mod process_manager; +pub mod process_manager; mod processor; pub mod scheduler; pub mod thread; mod event_hub; +mod interrupt; pub use process_manager::*; pub use processor::Processor; diff --git a/crate/process/src/process_manager.rs b/crate/process/src/process_manager.rs index 988d56d..3ece300 100644 --- a/crate/process/src/process_manager.rs +++ b/crate/process/src/process_manager.rs @@ -39,6 +39,7 @@ pub struct ProcessManager { procs: Vec>>, scheduler: Mutex>, wait_queue: Vec>>, + children: Vec>>, event_hub: Mutex>, exit_handler: fn(Pid), } @@ -49,6 +50,7 @@ impl ProcessManager { procs: new_vec_default(max_proc_num), scheduler: Mutex::new(scheduler), wait_queue: new_vec_default(max_proc_num), + children: new_vec_default(max_proc_num), event_hub: Mutex::new(EventHub::new()), exit_handler, } @@ -183,7 +185,7 @@ impl ProcessManager { let mut proc_lock = self.procs[target].lock(); let proc = proc_lock.as_ref().expect("process not exist"); match proc.status { - Status::Exited(_) => self.wait_queue[target].lock().retain(|&i| i != pid), + Status::Exited(_) => self.del_child(pid, target), _ => panic!("can not remove non-exited process"), } } @@ -210,13 +212,20 @@ impl ProcessManager { pub fn set_parent(&self, pid: Pid, target: Pid) { self.wait_queue[target].lock().push(pid); + self.children[pid].lock().push(target); } - pub fn del_parent(&self, pid: Pid, target: Pid) { + pub fn del_child(&self, pid: Pid, target: Pid) { self.wait_queue[target].lock().retain(|&i| i != pid); + self.children[pid].lock().retain(|&i| i != target); + } + pub fn get_children(&self, pid: Pid) -> Vec{ + self.children[pid].lock().clone() } pub fn exit(&self, pid: Pid, code: ExitCode) { - (self.exit_handler)(pid); + for child in self.children[pid].lock().drain(..) { + self.wait_queue[child].lock().retain(|&i| i != pid); + } self.set_status(pid, Status::Exited(code)); } /// Called when a process exit @@ -226,6 +235,7 @@ impl ProcessManager { } proc.context = None; + (self.exit_handler)(pid); } } fn new_vec_default(size: usize) -> Vec { diff --git a/crate/process/src/processor.rs b/crate/process/src/processor.rs index c1432ca..9ac5a0a 100644 --- a/crate/process/src/processor.rs +++ b/crate/process/src/processor.rs @@ -3,6 +3,7 @@ use alloc::sync::Arc; use spin::Mutex; use core::cell::UnsafeCell; use process_manager::*; +use interrupt; /// Process executor /// @@ -52,14 +53,15 @@ impl Processor { /// via switch back to the scheduler. pub fn run(&self) -> ! { let inner = self.inner(); + unsafe { interrupt::disable_and_store(); } loop { let proc = inner.manager.run(inner.id); trace!("CPU{} begin running process {}", inner.id, proc.0); inner.proc = Some(proc); unsafe { - inner.loop_context.switch_to(&mut *inner.proc.as_mut().unwrap().1); + inner.loop_context.switch_to(&mut *inner.proc.as_mut().expect("context should not be None").1); } - let (pid, context) = inner.proc.take().unwrap(); + let (pid, context) = inner.proc.take().expect("proc should not be None"); trace!("CPU{} stop running process {}", inner.id, pid); inner.manager.stop(pid, context); } @@ -70,12 +72,17 @@ impl Processor { pub fn yield_now(&self) { let inner = self.inner(); unsafe { + let flags = interrupt::disable_and_store(); inner.proc.as_mut().unwrap().1.switch_to(&mut *inner.loop_context); + interrupt::restore(flags); } } pub fn pid(&self) -> Pid { - self.inner().proc.as_ref().unwrap().0 + if self.inner().proc.is_none() { + return 0; + } + self.inner().proc.as_ref().expect("pid should not be None").0 } pub fn context(&self) -> &Context { @@ -93,3 +100,4 @@ impl Processor { } } } + diff --git a/crate/process/src/thread.rs b/crate/process/src/thread.rs index 3742a21..074b08a 100644 --- a/crate/process/src/thread.rs +++ b/crate/process/src/thread.rs @@ -97,6 +97,7 @@ pub fn spawn(f: F) -> JoinHandle // 在Processor中创建新的线程 let context = new_kernel_context(kernel_thread_entry::, f as usize); let pid = processor().manager().add(context); + processor().manager().set_parent(current().id(), pid); // 接下来看看`JoinHandle::join()`的实现 // 了解是如何获取f返回值的 diff --git a/crate/riscv b/crate/riscv index a37a65f..f358204 160000 --- a/crate/riscv +++ b/crate/riscv @@ -1 +1 @@ -Subproject commit a37a65fa13a00c5aa0068c3f2b5d55af6a37dd93 +Subproject commit f358204af01f2374ab6ed6ea059f724cd5f2fe6f diff --git a/kernel/src/fs.rs b/kernel/src/fs.rs index c90499d..01aeba0 100644 --- a/kernel/src/fs.rs +++ b/kernel/src/fs.rs @@ -20,6 +20,10 @@ _binary_user_riscv_img_end: pub fn shell() { // load riscv32/x86_64 user program + use sync; + sync::test::philosopher_using_mutex(); + sync::test::philosopher_using_monitor(); + info!("come into shell!"); #[cfg(target_arch = "riscv32")] let device = { diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index fdc197a..60497cb 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -31,7 +31,6 @@ pub fn init() { static PROCESSORS: [Processor; MAX_CPU_NUM] = [Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new()]; -/// Ugly solution for sys_wait(0) (wait for any child) #[derive(Default)] pub struct Process { parent: AtomicUsize, @@ -39,34 +38,9 @@ pub struct Process { } impl Process { - pub fn new_fork(pid: usize, parent: usize) { - PROCESS[pid].parent.store(parent, Ordering::Relaxed); - PROCESS[parent].children.lock().push(pid); - } pub fn proc_exit(pid: usize) { info!("proc_exit"); - for child in PROCESS[pid].children.lock().clone() { - info!("del child {}", child); - processor().manager().del_parent(pid, child); - } - } - pub fn get_children() -> Vec { - Self::current().children.lock().clone() - } - pub fn do_wait(pid: usize) { - Self::current().children.lock().retain(|&p| p != pid); } - fn current() -> &'static Self { - &PROCESS[thread::current().id()] - } -} - -lazy_static! { - pub static ref PROCESS: Vec = { - let mut vec = Vec::new(); - vec.resize_default(MAX_PROCESS_NUM); - vec - }; } /// Get current thread struct diff --git a/kernel/src/sync/test.rs b/kernel/src/sync/test.rs index 8ddb295..79c5574 100644 --- a/kernel/src/sync/test.rs +++ b/kernel/src/sync/test.rs @@ -103,7 +103,7 @@ fn philosopher(table: Arc) { }).collect(); for h in handles { - h.join().unwrap(); + h.join().expect("handle should not be none"); } println!("philosophers dining end"); } diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 0b755d0..0823beb 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -66,7 +66,6 @@ fn sys_fork(tf: &TrapFrame) -> i32 { //memory_set_map_swappable(context.get_memory_set_mut()); let pid = processor().manager().add(context); processor().manager().set_parent(thread::current().id(), pid); - Process::new_fork(pid, thread::current().id()); //memory_set_map_swappable(processor.get_context_mut(pid).get_memory_set_mut()); info!("fork: {} -> {}", thread::current().id(), pid); pid as i32 @@ -77,7 +76,7 @@ fn sys_fork(tf: &TrapFrame) -> i32 { fn sys_wait(pid: usize, code: *mut i32) -> i32 { loop { let wait_procs = match pid { - 0 => Process::get_children(), + 0 => processor().manager().get_children(thread::current().id()), _ => vec![pid], }; if wait_procs.is_empty() { @@ -90,7 +89,6 @@ fn sys_wait(pid: usize, code: *mut i32) -> i32 { unsafe { code.write(exit_code as i32); } } processor().manager().wait_done(thread::current().id(), pid); - Process::do_wait(pid); info!("wait: {} -> {}", thread::current().id(), pid); return 0; }