diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index d920143..ee81ec2 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -3,7 +3,7 @@ use std::{cell::RefCell, rc::Rc}; use crate::{simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}}}; use crate::kernel::synch::{Lock, Semaphore}; -use super::{system::System, thread::Thread}; +use super::{system::{System, self}, thread::Thread}; /// The halt system call. Stops Burritos. pub const SC_SHUTDOWN: u8 = 0; @@ -142,7 +142,7 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result todo!(), - SC_JOIN => todo!(), + SC_JOIN => sc_join(machine, system), SC_CREATE => todo!(), SC_OPEN => todo!(), SC_READ => todo!(), @@ -231,7 +231,7 @@ fn sc_v(machine: &mut Machine, system: &mut System) -> Result Result { let addr_name = machine.read_int_register(10) as usize; let initial_count = machine.read_int_register(11) as i32; - let size = get_length_param(addr_name as usize, machine); + let size = get_length_param(addr_name, machine); let _name = get_string_param(addr_name, size, machine); match initial_count < 0 { true => Err(format!("Initial_count < 0"))?, @@ -262,6 +262,7 @@ fn sc_new_thread(machine: &mut Machine, system: &mut System) -> Result { Rc::clone(th) @@ -274,25 +275,49 @@ fn sc_new_thread(machine: &mut Machine, system: &mut System) -> ResultAddObject(ptThread); + machine.write_int_register(10, tid as i64); Ok(MachineOk::Ok) } else { return Err("Process owner of current thread is none")?; } } -fn get_length_param(addr: usize, machine: & Machine) -> usize{ +fn sc_join(machine: &mut Machine, system: &mut System) -> Result { + let tid = machine.read_int_register(10); + let p_thread = system.get_thread_manager().get_obj_addrs().search_thread(tid as i32); + match p_thread { + Some(_) => { + if let Some(current_thread) = system.get_thread_manager().get_g_current_thread() { + let rc = Rc::clone(current_thread); + system.get_thread_manager().thread_join(machine, rc); + + Ok(MachineOk::Ok) + } else { + Ok(MachineOk::Ok) + } + }, + None => { + // Thread already terminated (type set to INVALID_TYPE) or call on an object + // that is not a thread + // Exit with no error code since we cannot separate the two cases + Ok(MachineOk::Ok) + } + } +} + +fn get_length_param(addr: usize, machine: & Machine) -> usize { let mut i = 0; let mut c = 1; - while c!= 0 { + while c != 0 { c = machine.read_memory(1, addr + i); - i+=1; + i +=1; } + println!("addr: {:x}, i: {}", addr, i + 1); i + 1 } -fn get_string_param(addr: usize, 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; @@ -300,12 +325,10 @@ fn get_string_param(addr: usize, maxlen: usize, machine: &Machine) -> Vec{ while c != 0 && i < maxlen { c = machine.read_memory(1, addr + i) as u8; - //dest.push(c as char); - dest[i] = c as char; + dest.push(c as char); i += 1; } - - dest[maxlen - 1] = '\0'; + dest.push('\0'); dest } diff --git a/src/main.rs b/src/main.rs index 5de60b9..bc9b050 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,7 +40,7 @@ fn main() { let args = Args::parse(); let mut machine = Machine::new(args.debug); - let (loader, ptr) = loader::Loader::new(args.executable.as_str(), &mut machine, 0).expect("IO Error"); + let (loader, ptr) = loader::Loader::new(args.executable.as_str(), &mut machine, 0).expect("An error occured while parsing the program"); let mut system = System::default(); diff --git a/src/simulator/loader.rs b/src/simulator/loader.rs index 3239cab..0820a4c 100644 --- a/src/simulator/loader.rs +++ b/src/simulator/loader.rs @@ -213,23 +213,23 @@ impl ElfHeader { } impl TryFrom<&Vec> for ElfHeader { - type Error = (); + type Error = String; fn try_from(instructions: &Vec) -> Result { if Self::is_elf(instructions) { let format = Self::is_32bits(instructions); let endianess = Self::check_endianess(instructions); - let version = Self::get_version(instructions).ok_or(())?; + let version = Self::get_version(instructions).ok_or("Cannot retrieve version")?; let is_sys_v_abi = Self::is_system_v_elf(instructions); let is_rv_target = Self::is_riscv_isa(instructions); - let entrypoint = Self::get_entrypoint(instructions, format).ok_or(())?; - let elf_header_size = Self::get_elf_header_size(instructions, format).ok_or(())?; - let program_header_location = Self::get_program_header_table_location(instructions, format).ok_or(())?; - let program_header_entries = Self::get_number_entries_program_header(instructions, format).ok_or(())? ; - let program_header_size = Self::get_program_header_size(instructions, format).ok_or(())?; - let section_header_location = Self::get_section_header_table_location(instructions, format).ok_or(())?; - let section_header_entries = Self::get_section_header_num_entries(instructions, format).ok_or(())?; - let section_header_size = Self::get_section_header_size(instructions, format).ok_or(())?; + let entrypoint = Self::get_entrypoint(instructions, format).ok_or("Cannot get entrypoint")?; + let elf_header_size = Self::get_elf_header_size(instructions, format).ok_or("Cannot get elf header size")?; + let program_header_location = Self::get_program_header_table_location(instructions, format).ok_or("Cannot get program header table location")?; + let program_header_entries = Self::get_number_entries_program_header(instructions, format).ok_or("Cannot get number of entries in program header table")? ; + let program_header_size = Self::get_program_header_size(instructions, format).ok_or("Cannot get program header entry size")?; + let section_header_location = Self::get_section_header_table_location(instructions, format).ok_or("Cannot get section header table location")?; + let section_header_entries = Self::get_section_header_num_entries(instructions, format).ok_or("Cannot get number of entries of section header")?; + let section_header_size = Self::get_section_header_size(instructions, format).ok_or("Cannot get size of section header entry")?; Ok(ElfHeader { endianess, is_32bits: format, @@ -246,7 +246,7 @@ impl TryFrom<&Vec> for ElfHeader { section_header_size }) } else { - Err(()) + Err("File doesn't have elf magic number")? } } } @@ -409,7 +409,7 @@ pub enum LoaderError { /// Correspond to std IO error IOError(std::io::Error), /// Others errors - ParsingError + ParsingError(String) } /// Global structure of the loader, one instance per loaded files @@ -455,7 +455,13 @@ impl Loader { let mut buf: [u8; 4] = [0; 4]; #[allow(clippy::needless_range_loop)] for k in 0..buf.len() { - buf[k] = self.bytes.get(section.image_offset as usize + j + k).copied().ok_or(LoaderError::ParsingError)?; + if section.does_flag_contains_key(FlagValue::ShfWrite) { + // flag WA, on doit allouer des données initialisés à 0 + // généralement, ce signifie que le compilateur à ajouter une section .bss + buf[k] = 0; + } else { + buf[k] = self.bytes.get(section.image_offset as usize + j + k).copied().ok_or(LoaderError::ParsingError(format!("index 0x{:x} is out of bound because list have a size of 0x{:x} (image offset 0x{:x}, j 0x{:x}, k 0x{:x})", section.image_offset as usize + j + k, self.bytes.len(), section.image_offset, j, k)))?; + } } machine.write_memory(4, start_index + section.virt_addr as usize + j, u32::from_le_bytes(buf) as u64); } @@ -492,8 +498,8 @@ impl Loader { Ok(header) => { header }, - Err(_) => { - return Err(LoaderError::ParsingError); + Err(err) => { + return Err(LoaderError::ParsingError(format!("Cannot parse elf header : {}", err))); } }; let section_header = match Self::parse_section_header(&instructions, elf_header.is_32bits, elf_header.section_header_location, elf_header.section_header_entries, elf_header.section_header_size) { @@ -501,7 +507,7 @@ impl Loader { header }, Err(_) => { - return Err(LoaderError::ParsingError); + return Err(LoaderError::ParsingError("Cannot parse section header".to_string())); } }; // #[cfg(debug_assertions)] diff --git a/src/utility/objaddr.rs b/src/utility/objaddr.rs index 33f17dd..e788eb0 100644 --- a/src/utility/objaddr.rs +++ b/src/utility/objaddr.rs @@ -2,9 +2,9 @@ //! their references. The ObjAddr struct //! allows to maintain this data structure. -use std::collections::HashMap; +use std::{collections::HashMap, cell::RefCell, rc::Rc}; -use crate::kernel::synch::{ Semaphore, Lock }; +use crate::kernel::{synch::{ Semaphore, Lock }, thread::Thread}; /// Brief Definition of object identifiers: /// @@ -19,7 +19,8 @@ use crate::kernel::synch::{ Semaphore, Lock }; pub struct ObjAddr { last_id: i32, semaphores: HashMap, - locks: HashMap + locks: HashMap, + threads: HashMap>>, } impl ObjAddr { @@ -29,7 +30,8 @@ impl ObjAddr { Self { last_id: 3, semaphores: HashMap::::new(), - locks: HashMap::::new() + locks: HashMap::::new(), + threads: HashMap::>>::new(), } } @@ -47,6 +49,13 @@ impl ObjAddr { self.last_id } + /// Adds the **obj** Lock to self + pub fn add_thread(&mut self, obj: Rc>) -> i32 { + self.last_id +=1; + self.threads.insert(self.last_id, obj); + self.last_id + } + /// Searches for a semaphore of id **id** in self pub fn search_semaphore(&mut self, id: i32) -> Option<&mut Semaphore> { self.semaphores.get_mut(&id) @@ -57,6 +66,11 @@ impl ObjAddr { self.locks.get_mut(&id) } + /// Searches for a lock of id **id** in self + pub fn search_thread(&mut self, id: i32) -> Option<&Rc>> { + self.threads.get(&id) + } + /// Removes the object of id **id** from self if it exists pub fn remove_semaphore(&mut self, id: i32) -> Option { self.semaphores.remove(&id) @@ -67,5 +81,10 @@ impl ObjAddr { self.locks.remove(&id) } + /// Remove the object of id **id** from self if it exists + pub fn remove_thread(&mut self, id: i32) -> Option>> { + self.threads.remove(&id) + } + } \ No newline at end of file diff --git a/test/syscall_tests/Makefile b/test/syscall_tests/Makefile index c374c49..8388949 100644 --- a/test/syscall_tests/Makefile +++ b/test/syscall_tests/Makefile @@ -1,4 +1,4 @@ -PROGRAMS = halt.guac prints.guac +PROGRAMS = halt.guac prints.guac producteur_consommateur.guac TOPDIR = ../.. include $(TOPDIR)/Makefile.rules diff --git a/test/syscall_tests/producteur_consommateur.c b/test/syscall_tests/producteur_consommateur.c new file mode 100644 index 0000000..f0126cb --- /dev/null +++ b/test/syscall_tests/producteur_consommateur.c @@ -0,0 +1,48 @@ +#include "userlib/syscall.h" +#include "userlib/libnachos.h" + + +const int N = 3; +int iplein = 0; +int ivide = 0; +int tab[3]; +SemId svide; +SemId splein; + +void producteur(); + +void consommateur(); + +int main() { + svide = SemCreate("producteur", N); + splein = SemCreate("consommateur", 0); + ThreadId producteurTh = threadCreate("producteur", producteur); + ThreadId consommateurTh = threadCreate("consommateur", consommateur); + Join(producteurTh); + Join(consommateurTh); + return 0; +} + +void producteur() { + for(int i = 0; i < 10; i++) + { + n_printf("batir une information\n"); + P(svide); + iplein = (iplein + 1) % N; + n_printf("communique une information : %d\n", i); + tab[iplein] = i; + V(splein); + } +} + +void consommateur() { + for(int i = 0; i < 10; i++) + { + P(splein); + ivide = (ivide +1) % N; + n_printf("recevoir une information\n"); + int info = tab[ivide]; + V(svide); + n_printf("exploiter l'information : %d\n", info); + } +}