Add Exit Exception

This commit is contained in:
Quentin Legot
2023-04-05 12:01:31 +02:00
parent 0fd2815a59
commit 24be35547e
4 changed files with 46 additions and 29 deletions

View File

@ -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<MachineOk, MachineError> {
pub fn call(exception: ExceptionType, machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
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<MachineOk, Ma
}
}
fn syscall(machine: &Machine) -> Result<MachineOk, MachineError> {
fn syscall(machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
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<MachineOk, MachineError> {
#[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);
}
}

View File

@ -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<RefCell<Thread>>) {
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);
}
}