Merge remote-tracking branch 'origin/thread_scheduler' into thread_scheduler
# Conflicts: # src/kernel/exception.rs
This commit is contained in:
@ -1,7 +1,9 @@
|
||||
use libc::printf;
|
||||
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;
|
||||
@ -42,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!(),
|
||||
@ -57,12 +59,19 @@ 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 => {
|
||||
let th = match &system.get_thread_manager().g_current_thread {
|
||||
Some(th) => th.clone(),
|
||||
None => Err("Current thread is None")?
|
||||
};
|
||||
system.get_thread_manager().thread_finish(machine, th);
|
||||
Ok(MachineOk::Ok)
|
||||
},
|
||||
SC_EXEC => todo!(),
|
||||
SC_JOIN => todo!(),
|
||||
SC_CREATE => todo!(),
|
||||
@ -96,7 +105,13 @@ fn syscall(machine: &Machine) -> Result<MachineOk, MachineError> {
|
||||
SC_PERROR => todo!(),
|
||||
SC_P => todo!(),
|
||||
SC_V => todo!(),
|
||||
SC_SEM_CREATE => todo!(),
|
||||
SC_SEM_CREATE => {
|
||||
let addr_name = machine.read_int_register(10);
|
||||
let initial_count = machine.read_int_register((11));
|
||||
let size = get_length_param(addr_name as usize, machine);
|
||||
Ok(MachineOk::Ok)
|
||||
|
||||
},
|
||||
SC_SEM_DESTROY => todo!(),
|
||||
SC_LOCK_CREATE => todo!(),
|
||||
SC_LOCK_DESTROY => todo!(),
|
||||
@ -120,6 +135,17 @@ fn syscall(machine: &Machine) -> Result<MachineOk, MachineError> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_length_param(addr: usize, machine: & Machine) -> usize{
|
||||
let mut i = 0;
|
||||
let mut c = 1;
|
||||
while c!= 0 {
|
||||
c = machine.read_memory(1, addr + i);
|
||||
i+=1;
|
||||
|
||||
}
|
||||
i + 1
|
||||
}
|
||||
|
||||
fn get_string_param(addr: i64, maxlen: i64, machine: &Machine) -> Vec<char>{
|
||||
let mut dest = Vec::with_capacity(maxlen as usize);
|
||||
|
||||
@ -141,6 +167,7 @@ fn get_string_param(addr: i64, maxlen: i64, machine: &Machine) -> Vec<char>{
|
||||
#[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;
|
||||
|
||||
@ -152,8 +179,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
|
||||
}
|
||||
@ -183,8 +210,8 @@ 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);
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
mod process;
|
||||
pub mod process;
|
||||
pub mod thread;
|
||||
pub mod mgerror;
|
||||
pub mod system;
|
||||
|
@ -16,7 +16,7 @@ macro_rules! get_new_thread {
|
||||
pub struct ThreadContext {
|
||||
pub int_registers: [i64; NUM_INT_REGS],
|
||||
pub float_registers: [f32; NUM_FP_REGS],
|
||||
pub pc: i64,
|
||||
pub pc: u64,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
@ -47,10 +47,10 @@ impl Thread {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_thread_context(&mut self, initial_pc_reg: i64, initial_sp: i64, arg: i64) {
|
||||
pub fn init_thread_context(&mut self, initial_pc_reg: u64, initial_sp: u64, arg: i64) {
|
||||
self.thread_context.pc = initial_pc_reg;
|
||||
self.thread_context.int_registers[10] = arg;
|
||||
self.thread_context.int_registers[STACK_REG] = initial_sp;
|
||||
self.thread_context.int_registers[STACK_REG] = initial_sp as i64;
|
||||
}
|
||||
|
||||
pub fn init_simulator_context(&self, base_stack_addr: [i8; SIMULATORSTACKSIZE]) {
|
||||
|
@ -78,17 +78,19 @@ impl ThreadManager {
|
||||
}
|
||||
},
|
||||
None => {
|
||||
|
||||
self.thread_restore_processor_state(machine, Rc::clone(&next_thread));
|
||||
// next_thread.restore_simulator_state();
|
||||
self.set_g_current_thread(Some(next_thread));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Start a thread, attaching it to a process
|
||||
pub fn start_thread(&mut self, thread: Rc<RefCell<Thread>>, owner: Process, func_pc: i64, argument: i64) {
|
||||
pub fn start_thread(&mut self, thread: Rc<RefCell<Thread>>, owner: Process, func_pc: u64, sp_loc: u64, argument: i64) {
|
||||
let mut thread_m = thread.borrow_mut();
|
||||
assert_eq!(thread_m.process, Option::None);
|
||||
thread_m.process = Option::Some(owner);
|
||||
let ptr = 0; // todo addrspace
|
||||
let ptr = sp_loc; // todo addrspace
|
||||
thread_m.init_thread_context(func_pc, ptr, argument);
|
||||
let base_stack_addr: [i8; SIMULATORSTACKSIZE] = [0; SIMULATORSTACKSIZE]; // todo AllocBoundedArray
|
||||
thread_m.init_simulator_context(base_stack_addr);
|
||||
@ -121,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() {
|
||||
@ -139,6 +141,8 @@ impl ThreadManager {
|
||||
let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff);
|
||||
self.g_thread_to_be_destroyed = Option::Some(Rc::clone(&thread));
|
||||
self.g_alive.remove(Rc::clone(&thread));
|
||||
#[cfg(debug_assertions)]
|
||||
println!("Sleeping thread {}", thread.borrow().get_name());
|
||||
// g_objets_addrs->removeObject(self.thread) // a ajouté plus tard
|
||||
self.thread_sleep(machine, Rc::clone(&thread));
|
||||
machine.interrupt.set_status(old_status);
|
||||
@ -153,6 +157,7 @@ impl ThreadManager {
|
||||
for i in 0..NUM_FP_REGS {
|
||||
t.thread_context.float_registers[i] = machine.read_fp_register(i);
|
||||
}
|
||||
t.thread_context.pc = machine.pc;
|
||||
}
|
||||
|
||||
/// Restore the CPU state of a user program on a context switch.
|
||||
@ -161,6 +166,7 @@ impl ThreadManager {
|
||||
for i in 0..NUM_INT_REGS {
|
||||
machine.write_int_register(i, t.thread_context.int_registers[i]);
|
||||
}
|
||||
machine.pc = t.thread_context.pc;
|
||||
}
|
||||
|
||||
/// Currently running thread
|
||||
@ -196,28 +202,42 @@ impl ThreadManager {
|
||||
mod test {
|
||||
use std::{rc::Rc, cell::RefCell};
|
||||
|
||||
use crate::{simulator::machine::Machine, kernel::{system::System, thread::Thread, process::Process}};
|
||||
use crate::{simulator::{machine::Machine, loader}, kernel::{system::System, thread::{Thread, self}, process::Process}};
|
||||
|
||||
#[test]
|
||||
#[ignore = "Pas encore terminé, contient des bugs"]
|
||||
fn test_thread_context() {
|
||||
let mut machine = Machine::init_machine();
|
||||
let mut system = System::default();
|
||||
let (loader, ptr1) = loader::Loader::new("./test/riscv_instructions/simple_arithmetics/unsigned_addition", &mut machine, 0).expect("IO Error");
|
||||
println!("{}", ptr1);
|
||||
let (loader2, ptr2) = loader::Loader::new("./test/riscv_instructions/syscall_tests/halt", &mut machine, ptr1 as usize).expect("IO Error");
|
||||
let start_pc = loader.elf_header.entrypoint;
|
||||
let system = &mut System::default();
|
||||
|
||||
let thread1 = Thread::new("th1");
|
||||
let thread1 = Rc::new(RefCell::new(thread1));
|
||||
system.get_thread_manager().get_g_alive().push(Rc::clone(&thread1));
|
||||
let owner = Process { num_thread: 0 };
|
||||
system.get_thread_manager().start_thread(Rc::clone(&thread1), owner, thread1_func as i64, 0);
|
||||
assert_eq!(thread1.borrow_mut().thread_context.pc, thread1_func as i64);
|
||||
let to_run = system.get_thread_manager().find_next_to_run().unwrap();
|
||||
assert_eq!(to_run, Rc::clone(&thread1));
|
||||
assert!(system.get_thread_manager().get_g_alive().contains(&Rc::clone(&thread1)));
|
||||
system.get_thread_manager().switch_to(&mut machine, Rc::clone(&to_run));
|
||||
|
||||
println!("{:#?}", thread1.borrow_mut().thread_context);
|
||||
}
|
||||
|
||||
fn thread1_func() {
|
||||
println!("Hello");
|
||||
let thread2 = Thread::new("th2");
|
||||
let thread2 = Rc::new(RefCell::new(thread2));
|
||||
system.get_thread_manager().get_g_alive().push(Rc::clone(&thread1));
|
||||
|
||||
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(&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(&thread1)));
|
||||
debug_assert_eq!(machine.pc, loader.elf_header.entrypoint);
|
||||
|
||||
machine.run(system);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user