From 37a6df252f549afc8841cc350a4e0e61fe3257c7 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Tue, 17 Jul 2018 00:23:02 +0800 Subject: [PATCH] Refactor process mod --- kernel/src/arch/riscv32/interrupt.rs | 2 +- kernel/src/arch/riscv32/io.rs | 8 +- kernel/src/arch/x86_64/interrupt/handler.rs | 11 +- kernel/src/fs.rs | 4 +- kernel/src/process/{process.rs => context.rs} | 103 +++++------------- kernel/src/process/mod.rs | 43 ++------ kernel/src/process/processor.rs | 77 +++++++++---- kernel/src/syscall.rs | 16 +-- kernel/src/thread.rs | 24 ++-- kernel/src/trap.rs | 18 ++- 10 files changed, 133 insertions(+), 173 deletions(-) rename kernel/src/process/{process.rs => context.rs} (64%) diff --git a/kernel/src/arch/riscv32/interrupt.rs b/kernel/src/arch/riscv32/interrupt.rs index e629e5e..843cdcd 100644 --- a/kernel/src/arch/riscv32/interrupt.rs +++ b/kernel/src/arch/riscv32/interrupt.rs @@ -41,7 +41,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { match tf.scause.cause() { Trap::Interrupt(SupervisorTimer) => timer(), Trap::Exception(UserEnvCall) => syscall(tf), - _ => panic!("Unhandled interrupt: {:?}\n{:#010x?}", tf.scause.cause(), tf), + _ => ::trap::error(tf), } ::trap::before_return(); trace!("Interrupt end"); diff --git a/kernel/src/arch/riscv32/io.rs b/kernel/src/arch/riscv32/io.rs index a0743a3..72c3d55 100644 --- a/kernel/src/arch/riscv32/io.rs +++ b/kernel/src/arch/riscv32/io.rs @@ -6,7 +6,7 @@ struct SerialPort; impl Write for SerialPort { fn write_str(&mut self, s: &str) -> Result { for c in s.bytes() { - if c == 8 { + if c == 127 { sbi::console_putchar(8); sbi::console_putchar(' ' as usize); sbi::console_putchar(8); @@ -20,9 +20,9 @@ impl Write for SerialPort { pub fn getchar() -> char { match sbi::console_getchar() as u8 { - 255 => 0, // null - c => c, - } as char + 255 => '\0', // null + c => c as char, + } } pub fn putfmt(fmt: Arguments) { diff --git a/kernel/src/arch/x86_64/interrupt/handler.rs b/kernel/src/arch/x86_64/interrupt/handler.rs index ee02605..b22156e 100644 --- a/kernel/src/arch/x86_64/interrupt/handler.rs +++ b/kernel/src/arch/x86_64/interrupt/handler.rs @@ -170,16 +170,7 @@ fn syscall32(tf: &mut TrapFrame) { } fn error(tf: &TrapFrame) { - use process::PROCESSOR; - if let Some(processor) = PROCESSOR.try() { - let mut processor = processor.lock(); - let pid = processor.current_pid(); - error!("Process {} error:\n{:#x?}", pid, tf); - processor.exit(pid, 0x100); // TODO: Exit code for error - } else { - error!("Exception {:#x} when processor not inited\n{:#x?}", tf.trap_num, tf); - loop {} - } + ::trap::error(tf); } #[no_mangle] diff --git a/kernel/src/fs.rs b/kernel/src/fs.rs index fff5417..fbb76d7 100644 --- a/kernel/src/fs.rs +++ b/kernel/src/fs.rs @@ -3,7 +3,6 @@ use alloc::boxed::Box; #[cfg(target_arch = "x86_64")] use arch::driver::ide; use spin::Mutex; -use process; pub fn shell() { #[cfg(target_arch = "riscv")] @@ -31,7 +30,8 @@ pub fn shell() { } if let Ok(file) = root.borrow().lookup(name.as_str()) { let len = file.borrow().read_at(0, &mut *buf).unwrap(); - process::add_user_process(name, &buf[..len]); + use process::*; + processor().add(Context::new_user(&buf[..len])); } else { println!("Program not exist"); } diff --git a/kernel/src/process/process.rs b/kernel/src/process/context.rs similarity index 64% rename from kernel/src/process/process.rs rename to kernel/src/process/context.rs index 935d251..5d82af8 100644 --- a/kernel/src/process/process.rs +++ b/kernel/src/process/context.rs @@ -1,57 +1,30 @@ -use alloc::String; -use arch::interrupt::*; +use arch::interrupt::{TrapFrame, Context as ArchContext}; use memory::{MemoryArea, MemoryAttr, MemorySet}; use xmas_elf::{ElfFile, header, program::{Flags, ProgramHeader, Type}}; +use core::fmt::{Debug, Error, Formatter}; -#[derive(Debug)] -pub struct Process { - pub(in process) pid: Pid, - pub(in process) parent: Pid, - pub(in process) name: String, - pub(in process) memory_set: MemorySet, - pub(in process) status: Status, - pub(in process) context: Context, +pub struct Context { + arch: ArchContext, + memory_set: MemorySet, } -pub type Pid = usize; -pub type ErrorCode = usize; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Status { - Ready, - Running, - Waiting(Pid), - Sleeping, - Exited(ErrorCode), -} - -impl Process { - /// Make a new kernel thread - pub fn new(name: &str, entry: extern fn(usize) -> !, arg: usize) -> Self { - let ms = MemorySet::new(); - let context = unsafe { Context::new_kernel_thread(entry, arg, ms.kstack_top(), ms.token()) }; +impl Context { + pub unsafe fn switch(&mut self, target: &mut Self) { + self.arch.switch(&mut target.arch); + } - Process { - pid: 0, - parent: 0, - name: String::from(name), - memory_set: ms, - status: Status::Ready, - context, + pub unsafe fn new_init() -> Self { + Context { + arch: ArchContext::null(), + memory_set: MemorySet::new(), } } - /// Make the first kernel thread `initproc` - /// Should be called only once - pub fn new_init() -> Self { - assert_has_not_been_called!(); - Process { - pid: 0, - parent: 0, - name: String::from("init"), - memory_set: MemorySet::new(), - status: Status::Running, - context: unsafe { Context::null() }, // will be set at first schedule + pub fn new_kernel(entry: extern fn(usize) -> !, arg: usize) -> Self { + let ms = MemorySet::new(); + Context { + arch: unsafe { ArchContext::new_kernel_thread(entry, arg, ms.kstack_top(), ms.token()) }, + memory_set: ms, } } @@ -100,20 +73,12 @@ impl Process { }); } - - // Allocate kernel stack and push trap frame - let context = unsafe { - Context::new_user_thread( - entry_addr, user_stack_top - 8, memory_set.kstack_top(), is32, memory_set.token()) - }; - - Process { - pid: 0, - parent: 0, - name: String::new(), + Context { + arch: unsafe { + ArchContext::new_user_thread( + entry_addr, user_stack_top - 8, memory_set.kstack_top(), is32, memory_set.token()) + }, memory_set, - status: Status::Ready, - context, } } @@ -123,7 +88,7 @@ impl Process { let memory_set = self.memory_set.clone(); // Copy data to temp space - use alloc::Vec; + use alloc::vec::Vec; let datas: Vec> = memory_set.iter().map(|area| { Vec::from(unsafe { area.as_slice() }) }).collect(); @@ -137,24 +102,16 @@ impl Process { }); } - // Push context at kstack top - let context = unsafe { Context::new_fork(tf, memory_set.kstack_top(), memory_set.token()) }; - - Process { - pid: 0, - parent: self.pid, - name: self.name.clone() + "_fork", + Context { + arch: unsafe { ArchContext::new_fork(tf, memory_set.kstack_top(), memory_set.token()) }, memory_set, - status: Status::Ready, - context, } } +} - pub fn exit_code(&self) -> Option { - match self.status { - Status::Exited(code) => Some(code), - _ => None, - } +impl Debug for Context { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + write!(f, "{:?}", self.arch) } } diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index ed88e5c..bdef0da 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -1,48 +1,21 @@ use alloc::String; -use memory::MemorySet; -use self::process::*; +pub use self::context::*; pub use self::processor::*; use spin::Once; -use sync::SpinNoIrqLock; +use sync::{SpinNoIrqLock, Mutex, MutexGuard, SpinNoIrq}; -mod process; +mod context; mod processor; mod scheduler; - pub fn init() { - PROCESSOR.call_once(|| { - SpinNoIrqLock::new({ - let initproc = Process::new_init(); - let idleproc = Process::new("idle", idle_thread, 0); - let mut processor = Processor::new(); - processor.add(initproc); - processor.add(idleproc); - processor - }) - }); + PROCESSOR.call_once(|| + SpinNoIrqLock::new(Processor::new(unsafe { Context::new_init() })) + ); } pub static PROCESSOR: Once> = Once::new(); -extern fn idle_thread(_arg: usize) -> ! { - println!("Hello, I'm idle."); - loop {} -} - -pub fn add_user_process(name: impl AsRef, data: &[u8]) { - let mut processor = PROCESSOR.try().unwrap().lock(); - let mut new = Process::new_user(data); - new.name = String::from(name.as_ref()); - processor.add(new); -} - -pub fn add_kernel_process(entry: extern fn(usize) -> !, arg: usize) -> Pid { - let mut processor = PROCESSOR.try().unwrap().lock(); - let new = Process::new("", entry, arg); - processor.add(new) -} - -pub fn print() { - debug!("{:#x?}", *PROCESSOR.try().unwrap().lock()); +pub fn processor() -> MutexGuard<'static, Processor, SpinNoIrq> { + PROCESSOR.try().unwrap().lock() } \ No newline at end of file diff --git a/kernel/src/process/processor.rs b/kernel/src/process/processor.rs index 140a370..903f846 100644 --- a/kernel/src/process/processor.rs +++ b/kernel/src/process/processor.rs @@ -1,9 +1,29 @@ use alloc::BTreeMap; use core::fmt::{Debug, Error, Formatter}; -use super::process::*; +use super::context::*; use super::scheduler::*; use util::{EventHub, GetMut2}; +#[derive(Debug)] +pub struct Process { + pid: Pid, + parent: Pid, + status: Status, + context: Context, +} + +pub type Pid = usize; +pub type ErrorCode = usize; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum Status { + Ready, + Running, + Waiting(Pid), + Sleeping, + Exited(ErrorCode), +} + pub struct Processor { procs: BTreeMap, current_pid: Pid, @@ -14,11 +34,30 @@ pub struct Processor { scheduler: RRScheduler, } +impl Process { + fn exit_code(&self) -> Option { + match self.status { + Status::Exited(code) => Some(code), + _ => None, + } + } +} + // TODO: 除schedule()外的其它函数,应该只设置进程状态,不应调用schedule impl Processor { - pub fn new() -> Self { + pub fn new(init_context: Context) -> Self { + let init_proc = Process { + pid: 0, + parent: 0, + status: Status::Running, + context: init_context, + }; Processor { - procs: BTreeMap::::new(), + procs: { + let mut map = BTreeMap::::new(); + map.insert(0, init_proc); + map + }, current_pid: 0, event_hub: EventHub::new(), next: None, @@ -28,7 +67,6 @@ impl Processor { } pub fn lab6_set_priority(&mut self, priority: u8) { - unimplemented!(); // self.scheduler.set_priority(self.current_pid, priority); } @@ -89,12 +127,15 @@ impl Processor { self.event_hub.get_time() } - pub fn add(&mut self, mut process: Process) -> Pid { + pub fn add(&mut self, context: Context) -> Pid { let pid = self.alloc_pid(); - process.pid = pid; - if process.status == Status::Ready { - self.scheduler.insert(pid); - } + let process = Process { + pid, + parent: self.current_pid, + status: Status::Ready, + context, + }; + self.scheduler.insert(pid); self.procs.insert(pid, process); pid } @@ -102,7 +143,7 @@ impl Processor { /// Called every interrupt end /// Do schedule ONLY IF current status != Running pub fn schedule(&mut self) { - if self.current().status == Status::Running { + if self.get(self.current_pid).status == Status::Running { return; } let pid = self.next.take().unwrap_or_else(|| self.scheduler.select().unwrap()); @@ -117,7 +158,7 @@ impl Processor { let pid0 = self.current_pid; if pid == self.current_pid { - if self.current().status != Status::Running { + if self.get(self.current_pid).status != Status::Running { self.set_status(pid, Status::Running); } return; @@ -137,7 +178,7 @@ impl Processor { use core::mem::forget; super::PROCESSOR.try().unwrap().force_unlock(); from.context.switch(&mut to.context); - forget(super::PROCESSOR.try().unwrap().lock()); + forget(super::processor()); } } @@ -147,8 +188,8 @@ impl Processor { fn get_mut(&mut self, pid: Pid) -> &mut Process { self.procs.get_mut(&pid).unwrap() } - pub fn current(&self) -> &Process { - self.get(self.current_pid) + pub fn current_context(&self) -> &Context { + &self.get(self.current_pid).context } pub fn current_pid(&self) -> Pid { self.current_pid @@ -215,14 +256,6 @@ impl Processor { } } -impl Debug for Processor { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - f.debug_map() - .entries(self.procs.iter().map(|(pid, proc0)| { (pid, &proc0.name) })) - .finish() - } -} - #[derive(Debug)] pub enum WaitResult { /// The target process is exited with `ErrorCode`. diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 8bac72e..60ab019 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -58,9 +58,9 @@ fn sys_close(fd: usize) -> i32 { /// Fork the current process. Return the child's PID. fn sys_fork(tf: &TrapFrame) -> i32 { - let mut processor = PROCESSOR.try().unwrap().lock(); - let new = processor.current().fork(tf); - let pid = processor.add(new); + let mut processor = processor(); + let context = processor.current_context().fork(tf); + let pid = processor.add(context); info!("fork: {} -> {}", processor.current_pid(), pid); pid as i32 } @@ -68,7 +68,7 @@ fn sys_fork(tf: &TrapFrame) -> i32 { /// Wait the process exit. /// Return the PID. Store exit code to `code` if it's not null. fn sys_wait(pid: usize, code: *mut i32) -> i32 { - let mut processor = PROCESSOR.try().unwrap().lock(); + let mut processor = processor(); match processor.current_wait_for(pid) { WaitResult::Ok(pid, error_code) => { if !code.is_null() { @@ -87,7 +87,7 @@ fn sys_yield() -> i32 { /// Kill the process fn sys_kill(pid: usize) -> i32 { - PROCESSOR.try().unwrap().lock().kill(pid); + processor().kill(pid); 0 } @@ -98,7 +98,7 @@ fn sys_getpid() -> i32 { /// Exit the current process fn sys_exit(error_code: usize) -> i32 { - let mut processor = PROCESSOR.try().unwrap().lock(); + let mut processor = processor(); let pid = processor.current_pid(); processor.exit(pid, error_code); 0 @@ -111,12 +111,12 @@ fn sys_sleep(time: usize) -> i32 { } fn sys_get_time() -> i32 { - let processor = PROCESSOR.try().unwrap().lock(); + let processor = processor(); processor.get_time() as i32 } fn sys_lab6_set_priority(priority: usize) -> i32 { - let mut processor = PROCESSOR.try().unwrap().lock(); + let mut processor = processor(); processor.lab6_set_priority(priority as u8); 0 } diff --git a/kernel/src/thread.rs b/kernel/src/thread.rs index b3749d4..f4968e6 100644 --- a/kernel/src/thread.rs +++ b/kernel/src/thread.rs @@ -14,7 +14,7 @@ use process::*; /// Gets a handle to the thread that invokes it. pub fn current() -> Thread { Thread { - pid: PROCESSOR.try().unwrap().lock().current_pid(), + pid: processor().current_pid(), } } @@ -22,7 +22,7 @@ pub fn current() -> Thread { pub fn sleep(dur: Duration) { let time = dur_to_ticks(dur); info!("sleep: {:?} ticks", time); - let mut processor = PROCESSOR.try().unwrap().lock(); + let mut processor = processor(); let pid = processor.current_pid(); processor.sleep(pid, time); processor.schedule(); @@ -39,9 +39,8 @@ pub fn spawn(f: F) -> JoinHandle T: Send + 'static, { info!("spawn:"); - use process; let f = Box::into_raw(Box::new(f)); - let pid = process::add_kernel_process(kernel_thread_entry::, f as usize); + let pid = processor().add(Context::new_kernel(kernel_thread_entry::, f as usize)); return JoinHandle { thread: Thread { pid }, mark: PhantomData, @@ -55,7 +54,7 @@ pub fn spawn(f: F) -> JoinHandle let f = unsafe { Box::from_raw(f as *mut F) }; let ret = Box::new(f()); unsafe { LocalKey::::get_map() }.clear(); - let mut processor = PROCESSOR.try().unwrap().lock(); + let mut processor = processor(); let pid = processor.current_pid(); processor.exit(pid, Box::into_raw(ret) as usize); processor.schedule(); @@ -66,7 +65,7 @@ pub fn spawn(f: F) -> JoinHandle /// Cooperatively gives up a timeslice to the OS scheduler. pub fn yield_now() { info!("yield:"); - let mut processor = PROCESSOR.try().unwrap().lock(); + let mut processor = processor(); processor.set_reschedule(); processor.schedule(); } @@ -74,7 +73,7 @@ pub fn yield_now() { /// Blocks unless or until the current thread's token is made available. pub fn park() { info!("park:"); - let mut processor = PROCESSOR.try().unwrap().lock(); + let mut processor = processor(); let pid = processor.current_pid(); processor.sleep_(pid); processor.schedule(); @@ -88,7 +87,7 @@ pub struct Thread { impl Thread { /// Atomically makes the handle's token available if it is not already. pub fn unpark(&self) { - let mut processor = PROCESSOR.try().unwrap().lock(); + let mut processor = processor(); processor.wakeup_(self.pid); } /// Gets the thread's unique identifier. @@ -110,13 +109,10 @@ impl JoinHandle { } /// Waits for the associated thread to finish. pub fn join(self) -> Result { - let mut processor = PROCESSOR.try().unwrap().lock(); + let mut processor = processor(); match processor.current_wait_for(self.thread.pid) { - WaitResult::Ok(_, exit_code) => { - unsafe { - let value = Box::from_raw(exit_code as *mut T); - Ok(ptr::read(exit_code as *const T)) - } + WaitResult::Ok(_, exit_code) => unsafe { + Ok(*Box::from_raw(exit_code as *mut T)) } WaitResult::NotExist => Err(()), } diff --git a/kernel/src/trap.rs b/kernel/src/trap.rs index be91528..6f667f3 100644 --- a/kernel/src/trap.rs +++ b/kernel/src/trap.rs @@ -1,14 +1,24 @@ -use process::PROCESSOR; - +use process::*; +use arch::interrupt::TrapFrame; pub fn timer() { - let mut processor = PROCESSOR.try().unwrap().lock(); + let mut processor = processor(); processor.tick(); } pub fn before_return() { - use process::PROCESSOR; if let Some(processor) = PROCESSOR.try() { processor.lock().schedule(); } +} + +pub fn error(tf: &TrapFrame) { + if let Some(processor) = PROCESSOR.try() { + let mut processor = processor.lock(); + let pid = processor.current_pid(); + error!("Process {} error:\n{:#x?}", pid, tf); + processor.exit(pid, 0x100); // TODO: Exit code for error + } else { + panic!("Exception when processor not inited\n{:#x?}", tf); + } } \ No newline at end of file