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 9df6a69..a013c13 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 9b56c48..518dcbd 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); } @@ -71,12 +73,17 @@ impl Processor { trace!("yield start"); 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().expect("pid should not be none").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 { @@ -94,3 +101,4 @@ impl Processor { } } } + diff --git a/crate/process/src/thread.rs b/crate/process/src/thread.rs index a0e9048..4dc7e45 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/kernel/src/fs.rs b/kernel/src/fs.rs index 025cdad..456e422 100644 --- a/kernel/src/fs.rs +++ b/kernel/src/fs.rs @@ -20,6 +20,12 @@ _binary_user_riscv_img_end: pub fn shell() { // load riscv32/x86_64 user program + use sync; + /// below are test for sync, uncomment them if need + //sync::test::philosopher_using_mutex(); + //sync::test::philosopher_using_monitor(); + + info!("come into shell!"); #[cfg(target_arch = "riscv32")] let device = { @@ -43,9 +49,6 @@ pub fn shell() { let layout = Layout::from_size_align(BUF_SIZE, 0x1000).unwrap(); let buf = unsafe{ slice::from_raw_parts_mut(alloc(layout), BUF_SIZE) }; // start interaction - use sync; - //sync::test::philosopher_using_mutex(); - //sync::test::philosopher_using_monitor(); loop { print!(">> "); 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 43a4615..7c8fdeb 100644 --- a/kernel/src/sync/test.rs +++ b/kernel/src/sync/test.rs @@ -105,7 +105,7 @@ fn philosopher(table: Arc) { trace!("philosopher starting finish"); for h in handles { - h.join().expect("join expects some value"); + 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; }