diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index 5a96b44..0cf5921 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -1,5 +1,9 @@ +use std::rc::Rc; + use crate::simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}}; +use super::system::System; + pub const SC_SHUTDOWN: u8 = 0; pub const SC_EXIT: u8 = 1; @@ -40,11 +44,11 @@ pub const SC_DEBUG: u8 = 34; pub const CONSOLE_OUTPUT: u8 = 1; // todo : returns new types, not just machine errors and machine ok -pub fn call(exception: ExceptionType, machine: &Machine) -> Result { +pub fn call(exception: ExceptionType, machine: &mut Machine, system: &mut System) -> Result { match exception { ExceptionType::NoException => todo!(), - ExceptionType::SyscallException => syscall(machine), + ExceptionType::SyscallException => syscall(machine, system), ExceptionType::PagefaultException => todo!(), ExceptionType::ReadOnlyException => todo!(), ExceptionType::BusErrorException => todo!(), @@ -55,12 +59,23 @@ pub fn call(exception: ExceptionType, machine: &Machine) -> Result Result { +fn syscall(machine: &mut Machine, system: &mut System) -> Result { let call_type = machine.read_int_register(17) as u8; match call_type { SC_SHUTDOWN => Ok(MachineOk::Shutdown), - SC_EXIT => todo!(), + SC_EXIT => { + match &system.get_thread_manager().g_current_thread { + Some(th) => { + let th = Rc::clone(th); + system.get_thread_manager().thread_finish(machine, th); + Ok(MachineOk::Ok) + }, + None => { + Err("Current thread is None".into()) + } + } + }, SC_EXEC => todo!(), SC_JOIN => todo!(), SC_CREATE => todo!(), @@ -121,6 +136,7 @@ fn syscall(machine: &Machine) -> Result { #[cfg(test)] mod test { use crate::kernel::exception::{SC_SHUTDOWN, SC_WRITE}; + use crate::kernel::system::System; use crate::simulator::instruction::Instruction; use crate::simulator::machine::Machine; @@ -132,8 +148,8 @@ mod test { machine.write_memory(4, 0, 0b000000000000_00000_000_00000_1110011); // ecall machine.write_memory(4, 4, 0b000000001010_00000_000_00001_0010011); // r1 <- 10 - - machine.run(); + let mut system = System::default(); + machine.run(&mut system); // If the machine was stopped with no error, the shutdown worked assert_ne!(machine.read_int_register(1), 10); // Check if the next instruction was executed } @@ -162,9 +178,9 @@ mod test { machine.write_memory(4, 4, 0b000000000000_00000_000_10001_0010011); // r17 <- SC_SHUTDOWN machine.write_memory(4, 8, 0b000000000000_00000_000_00000_1110011); // ecall - - - machine.run(); + + let mut system = System::default(); + machine.run(&mut system); } } \ No newline at end of file diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index ad123f3..3b558bc 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -123,8 +123,8 @@ impl ThreadManager { /// Put the thread to sleep and relinquish the processor pub fn thread_sleep(&mut self, machine: &mut Machine, thread: Rc>) { - assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); - assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff); + debug_assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); + debug_assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff); let mut next_thread = self.find_next_to_run(); while next_thread.is_none() { @@ -220,22 +220,22 @@ mod test { let thread2 = Rc::new(RefCell::new(thread2)); system.get_thread_manager().get_g_alive().push(Rc::clone(&thread1)); - let owner2 = Process { num_thread: 0 }; - system.get_thread_manager().start_thread(Rc::clone(&thread2), owner2, ptr1 + loader2.elf_header.entrypoint, ptr2 , -1); - let owner1 = Process { num_thread: 0 }; system.get_thread_manager().start_thread(Rc::clone(&thread1), owner1, loader.elf_header.entrypoint, ptr1, -1); debug_assert_eq!(thread1.borrow_mut().thread_context.pc, start_pc); debug_assert!(system.get_thread_manager().get_g_alive().contains(&Rc::clone(&thread1))); + let owner2 = Process { num_thread: 0 }; + system.get_thread_manager().start_thread(Rc::clone(&thread2), owner2, ptr1 + loader2.elf_header.entrypoint, ptr2 , -1); + let to_run = system.get_thread_manager().find_next_to_run().unwrap(); - debug_assert_eq!(to_run, Rc::clone(&thread2)); + debug_assert_eq!(to_run, Rc::clone(&thread1)); system.get_thread_manager().switch_to(&mut machine, Rc::clone(&to_run)); - debug_assert_eq!(system.get_thread_manager().g_current_thread, Option::Some(Rc::clone(&thread2))); - debug_assert_eq!(machine.pc, ptr1 + loader2.elf_header.entrypoint); + debug_assert_eq!(system.get_thread_manager().g_current_thread, Option::Some(Rc::clone(&thread1))); + debug_assert_eq!(machine.pc, loader.elf_header.entrypoint); - machine.run(); + machine.run(system); } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 9fe5976..73a439f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,6 @@ use simulator::machine::Machine; fn main() { let mut machine = Machine::init_machine(); - let system = System::default(); - machine.run() + let mut system = System::default(); + machine.run(&mut system); } diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index cf320a5..123b43b 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -15,13 +15,13 @@ use std::{ io::Write, fs::File }; -use crate::simulator::{ +use crate::{simulator::{ error::MachineError, instruction::{*, self}, interrupt::Interrupt, global::*, register::* -}; +}, kernel::system::System}; use crate::kernel::{ exception @@ -226,11 +226,11 @@ impl Machine { s } - pub fn raise_exception(&mut self, exception: ExceptionType, address : u64) -> Result{ + pub fn raise_exception(&mut self, exception: ExceptionType, address : u64, system: &mut System) -> Result{ self.set_status(MachineStatus::SystemMode); // Handle the interruption - match exception::call(exception, self) { + match exception::call(exception, self, system) { Ok(MachineOk::Shutdown) => { self.set_status(MachineStatus::UserMode); return Ok(MachineOk::Shutdown); @@ -246,9 +246,9 @@ impl Machine { /// ### Parameters /// /// - **machine** which contains a table of instructions - pub fn run(&mut self) { + pub fn run(&mut self, system: &mut System) { loop { - match self.one_instruction() { + match self.one_instruction(system) { Ok(MachineOk::Ok) => println!("hello"), Ok(MachineOk::Shutdown) => break, Err(e) => { if e.to_string().contains("System") { break; } panic!("FATAL at pc {} -> {}", self.pc, e) } @@ -262,7 +262,7 @@ impl Machine { /// ### Parameters /// /// - **machine** which contains a table of instructions and a pc to the actual instruction - pub fn one_instruction(&mut self) -> Result { + pub fn one_instruction(&mut self, system: &mut System) -> Result { if self.main_memory.len() <= self.pc as usize { panic!("ERROR : number max of instructions rushed"); @@ -335,7 +335,7 @@ impl Machine { RISCV_FP => self.fp_instruction(inst), // Treatment for: SYSTEM CALLS - RISCV_SYSTEM => self.raise_exception(ExceptionType::SyscallException, self.pc), + RISCV_SYSTEM => self.raise_exception(ExceptionType::SyscallException, self.pc, system), // Default case _ => Err(format!("{:x}: Unknown opcode\npc: {:x}", inst.opcode, self.pc))? @@ -710,7 +710,8 @@ mod test { let memory_before = mem_cmp::MemChecker::from(get_full_path!("memory", $a)).unwrap(); let memory_after = mem_cmp::MemChecker::from(get_full_path!("memory", &end_file_name)).unwrap(); mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); - m.run(); + let mut system = crate::kernel::system::System::default(); + m.run(&mut system); let expected_trace = fs::read_to_string(get_full_path!("reg_trace", $a)).unwrap(); assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); assert!(expected_trace.contains(m.registers_trace.as_str()));