diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index ee81ec2..a396718 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -286,14 +286,15 @@ fn sc_join(machine: &mut Machine, system: &mut System) -> Result { + Some(waiting_for) => { + let rc_waiting_for = Rc::clone(waiting_for); 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); + let rc_curr = Rc::clone(current_thread); + system.get_thread_manager().thread_join(machine, rc_curr, rc_waiting_for); Ok(MachineOk::Ok) } else { - Ok(MachineOk::Ok) + Err("Current should not be None")? } }, None => { @@ -347,7 +348,7 @@ 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 - let mut system = System::default(); + let mut system = System::new(true); 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 @@ -378,7 +379,7 @@ 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 - let mut system = System::default(); + let mut system = System::new(true); machine.run(&mut system); } diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index 0ca7d24..0baa892 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -233,7 +233,7 @@ mod test { #[test] fn test_lock_simple() { let mut machine = Machine::new(true); - let mut tm = ThreadManager::new(); + let mut tm = ThreadManager::new(true); let thread = Rc::new(RefCell::new(Thread::new("test_lock"))); tm.ready_to_run(Rc::clone(&thread)); tm.set_g_current_thread(Some(Rc::clone(&thread))); @@ -255,7 +255,7 @@ mod test { let thread2 = Rc::new(RefCell::new(Thread::new("test_lock2"))); let mut machine = Machine::new(true); - let mut tm = ThreadManager::new(); + let mut tm = ThreadManager::new(true); tm.ready_to_run(Rc::clone(&thread1)); tm.ready_to_run(Rc::clone(&thread2)); diff --git a/src/kernel/system.rs b/src/kernel/system.rs index 29c41b6..c70e064 100644 --- a/src/kernel/system.rs +++ b/src/kernel/system.rs @@ -20,6 +20,10 @@ pub struct System { impl System { + pub fn new(debug: bool) -> Self { + Self { thread_manager: ThreadManager::new(debug) } + } + // GETTERS pub fn get_thread_manager(&mut self) -> &mut ThreadManager { @@ -27,11 +31,3 @@ impl System { } } - -impl Default for System { - /// System constructor - fn default() -> Self { - Self { thread_manager: ThreadManager::new() } - } -} - diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 96c73eb..6878c63 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -19,19 +19,21 @@ pub struct ThreadManager { pub g_alive: List>>, /// Thread in ready state waiting to become active ready_list: List>>, - obj_addrs: ObjAddr + obj_addrs: ObjAddr, + debug: bool } impl ThreadManager { /// Thread manager constructor - pub fn new() -> Self { + pub fn new(debug: bool) -> Self { Self { g_current_thread: Option::None, g_thread_to_be_destroyed: Option::None, g_alive: List::default(), ready_list: List::default(), obj_addrs: ObjAddr::init(), + debug } } @@ -74,6 +76,7 @@ impl ThreadManager { self.thread_save_processor_state(machine, old1); // old_thread.save_simulator_state(); if old2 != next_thread { + self.debug(format!("switching from \"{}\" to \"{}\"", old2.borrow().get_name(), next_thread.borrow().get_name())); self.thread_restore_processor_state(machine, Rc::clone(&next_thread)); // next_thread.restore_simulator_state(); self.set_g_current_thread(Some(next_thread)); @@ -85,28 +88,30 @@ impl ThreadManager { self.set_g_current_thread(Some(next_thread)); } } + + if let Some(th) = self.get_g_thread_to_be_destroyed() { + drop(th); + self.g_thread_to_be_destroyed = None + } } /// Start a thread, attaching it to a process 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); + thread_m.process = Option::Some(Rc::clone(&owner)); let ptr = sp_loc; // todo addrspace thread_m.init_thread_context(func_pc, ptr, argument); - if let Some(process) = &thread_m.process { - process.borrow_mut().num_thread += 1; - } else { - - } + owner.borrow_mut().num_thread += 1; self.get_g_alive().push(Rc::clone(&thread)); self.ready_to_run(Rc::clone(&thread)); } /// Wait for another thread to finish its execution - pub fn thread_join(&mut self, machine: &mut Machine, id_thread: Rc>) { - while self.get_g_alive().contains(&Rc::clone(&id_thread)) { - self.thread_yield(machine, Rc::clone(&id_thread)); + pub fn thread_join(&mut self, machine: &mut Machine, waiter: Rc>, waiting_for: Rc>) { + let waiting_for = Rc::clone(&waiting_for); + while self.get_g_alive().contains(&waiting_for) { + self.thread_yield(machine, Rc::clone(&waiter)); } } @@ -116,7 +121,9 @@ impl ThreadManager { pub fn thread_yield(&mut self, machine: &mut Machine, thread: Rc>) { let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff); - assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); + + self.debug(format!("Yeilding thread: {}", thread.borrow().get_name())); + debug_assert_eq!(&Option::Some(Rc::clone(&thread)), self.get_g_current_thread()); let next_thread = self.find_next_to_run(); if let Some(next_thread) = next_thread { self.ready_to_run(thread); @@ -145,8 +152,7 @@ impl ThreadManager { let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); self.set_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()); + self.debug(format!("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); @@ -305,6 +311,12 @@ impl ThreadManager { &mut self.obj_addrs } + fn debug(&self, message: String) { + if self.debug { + println!("{}", message); + } + } + } #[cfg(test)] @@ -319,7 +331,7 @@ mod test { let (loader, ptr) = loader::Loader::new("./target/guac/halt.guac", &mut machine, 0).expect("IO Error"); let start_pc = loader.elf_header.entrypoint; - let system = &mut System::default(); + let system = &mut System::new(true); let thread1 = Thread::new("th1"); let thread1 = Rc::new(RefCell::new(thread1)); @@ -345,7 +357,7 @@ mod test { fn test_semaphore_single() { // Init let mut machine = Machine::new(true); - let mut thread_manager = ThreadManager::new(); + let mut thread_manager = ThreadManager::new(true); let semaphore = Semaphore::new(1); let sema_id = thread_manager.get_obj_addrs().add_semaphore(semaphore); let thread = Rc::new(RefCell::new(Thread::new("test_semaphore"))); @@ -370,7 +382,7 @@ mod test { #[test] fn test_semaphore_multiple() { // Init - let mut tm = ThreadManager::new(); + let mut tm = ThreadManager::new(true); let mut machine = Machine::new(true); let semaphore = Semaphore::new(2); let sema_id = tm.get_obj_addrs().add_semaphore(semaphore); diff --git a/src/main.rs b/src/main.rs index bc9b050..7dcffb6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,7 +42,7 @@ fn main() { let mut machine = Machine::new(args.debug); 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(); + let mut system = System::new(args.debug); let thread_exec = Thread::new(args.executable.as_str()); let thread_exec = Rc::new(RefCell::new(thread_exec)); diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index b5237ac..a58eddd 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -725,7 +725,7 @@ 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); - let mut system = crate::kernel::system::System::default(); + let mut system = crate::kernel::system::System::new(true); m._run_debug(&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));