From a36e470ea1533e8f110bab3b29f65b627141642c Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Tue, 11 Apr 2023 17:47:36 +0200 Subject: [PATCH] Add new thread exception (untested) --- Cargo.toml | 1 + src/kernel/exception.rs | 43 +++++++++++++++++++++++++++++++----- src/kernel/thread.rs | 10 ++++++++- src/kernel/thread_manager.rs | 9 ++++++-- src/main.rs | 1 + 5 files changed, 56 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9359839..cd1e3d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "burritos" +rust-version = "1.64" version = "0.1.0" edition = "2021" diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index 7261f8b..e2774d5 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -1,6 +1,8 @@ +use std::{cell::RefCell, rc::Rc}; + use crate::simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}}; -use super::system::System; +use super::{system::System, thread::Thread}; /// The halt system call. Stops Burritos. pub const SC_SHUTDOWN: u8 = 0; @@ -165,13 +167,44 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result todo!(), SC_CLOSE => todo!(), - SC_NEW_THREAD => todo!(), + SC_NEW_THREAD => { + // Get the address of the string for the name of the thread + let name_addr = machine.read_int_register(10) as usize; + // Get the pointer of the function to be executed in the new thread + let func = machine.read_int_register(11); + // Get function parameters + let args = machine.read_int_register(12); + // get string name + let name_size = get_length_param(name_addr, machine); + let thread_name: String = get_string_param(name_addr, name_size, machine).into_iter().collect(); + + let n_thread = Thread::new(thread_name.as_str()); + let n_thread = Rc::new(RefCell::new(n_thread)); + let current_thread = match system.get_thread_manager().get_g_current_thread() { + Some(th) => { + Rc::clone(th) + }, + None => { + return Err("Current thread is none")?; + } + }; + let current_thread = current_thread.borrow_mut(); + if let Some(process) = current_thread.get_process_owner() { + system.get_thread_manager().start_thread(n_thread, Rc::clone(&process), func as u64, current_thread.thread_context.int_registers[2] as u64, args); + // TODO changé la valeur de sp quand on supportera les addresses virtuels + // machine.write_fp_register(10, tid); // tid obtenu en faisant int32_t tid = g_object_addrs->AddObject(ptThread); + Ok(MachineOk::Ok) + } else { + return Err("Process owner of current thread is none")?; + } + + }, SC_YIELD => todo!(), SC_PERROR => todo!(), SC_P => todo!(), SC_V => todo!(), SC_SEM_CREATE => { - let addr_name = machine.read_int_register(10); + let addr_name = machine.read_int_register(10) as usize; let initial_count = machine.read_int_register(11); let size = get_length_param(addr_name as usize, machine); let _name = get_string_param(addr_name, size, machine); @@ -216,14 +249,14 @@ fn get_length_param(addr: usize, machine: & Machine) -> usize{ i + 1 } -fn get_string_param(addr: i64, maxlen: usize, machine: &Machine) -> Vec{ +fn get_string_param(addr: usize, maxlen: usize, machine: &Machine) -> Vec{ let mut dest = Vec::with_capacity(maxlen); let mut i: usize = 0; let mut c = 1; while c != 0 && i < maxlen { - c = machine.read_memory(1, addr as usize + i) as u8; + c = machine.read_memory(1, addr + i) as u8; //dest.push(c as char); dest[i] = c as char; i += 1; diff --git a/src/kernel/thread.rs b/src/kernel/thread.rs index e6fd463..4e661c4 100644 --- a/src/kernel/thread.rs +++ b/src/kernel/thread.rs @@ -1,3 +1,5 @@ +use std::{rc::Rc, cell::RefCell}; + use super::{process::Process, system::ObjectType}; use crate::{simulator::machine::{NUM_INT_REGS, NUM_FP_REGS, STACK_REG}}; @@ -22,7 +24,7 @@ pub struct ThreadContext { #[derive(PartialEq, Debug)] pub struct Thread { name: String, - pub process: Option, + pub process: Option>>, pub thread_context: ThreadContext, pub stack_pointer: i32, object_type: ObjectType @@ -66,6 +68,12 @@ impl Thread { self.name.clone() } + /// Return reference to an optional Process + /// can be None if Thread hasn't been initialize + pub fn get_process_owner(&self) -> &Option>> { + &self.process + } + } impl Drop for Thread { diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 9a2e72e..ee0bd86 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -86,13 +86,17 @@ impl ThreadManager { } /// Start a thread, attaching it to a process - pub fn start_thread(&mut self, thread: Rc>, owner: Process, func_pc: u64, sp_loc: u64, argument: i64) { + pub fn start_thread(&mut self, thread: Rc>, owner: Rc>, 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 = sp_loc; // todo addrspace thread_m.init_thread_context(func_pc, ptr, argument); - thread_m.process.as_mut().unwrap().num_thread += 1; + if let Some(process) = &thread_m.process { + process.borrow_mut().num_thread += 1; + } else { + + } self.get_g_alive().push(Rc::clone(&thread)); self.ready_to_run(Rc::clone(&thread)); } @@ -215,6 +219,7 @@ mod test { system.get_thread_manager().get_g_alive().push(Rc::clone(&thread1)); let owner1 = Process { num_thread: 0 }; + let owner1 = Rc::new(RefCell::new(owner1)); system.get_thread_manager().start_thread(Rc::clone(&thread1), owner1, loader.elf_header.entrypoint, ptr, -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))); diff --git a/src/main.rs b/src/main.rs index 6b77e06..c75f916 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,6 +48,7 @@ fn main() { system.get_thread_manager().get_g_alive().push(Rc::clone(&thread_exec)); let owner1 = Process { num_thread: 0 }; + let owner1 = Rc::new(RefCell::new(owner1)); system.get_thread_manager().start_thread(Rc::clone(&thread_exec), owner1, loader.elf_header.entrypoint, ptr, -1); let to_run = system.get_thread_manager().find_next_to_run().unwrap();