Simplified Rc<RefCell<Thread>>

This commit is contained in:
François Autin 2023-04-20 11:31:25 +02:00
parent 780ed4b461
commit bb1d2383bb

View File

@ -90,21 +90,27 @@ use crate::{
MachineOk, MachineOk,
MachineError MachineError
} }
},
kernel::{
thread::Thread,
process::Process
} }
}; };
use super::{thread::Thread, process::Process}; /// Using this type alias to simplify struct and method definitions
type ThreadRef = Rc<RefCell<Thread>>;
/// # Thread manager /// # Thread manager
/// ///
/// An instance of this struct is responsible for managing threads on behalf of the system /// An instance of this struct is responsible for managing threads on behalf of the system
#[derive(PartialEq)] #[derive(PartialEq)]
pub struct ThreadManager { pub struct ThreadManager {
/// Current running thread /// Current running thread
pub g_current_thread: Option<Rc<RefCell<Thread>>>, pub g_current_thread: Option<ThreadRef>,
/// The list of alive threads /// The list of alive threads
pub g_alive: List<Rc<RefCell<Thread>>>, pub g_alive: List<ThreadRef>,
/// Thread in ready state waiting to become active /// Thread in ready state waiting to become active
ready_list: List<Rc<RefCell<Thread>>>, ready_list: List<ThreadRef>,
/// List of objects created by the thread manager (such as Locks and Semaphores) /// List of objects created by the thread manager (such as Locks and Semaphores)
obj_addrs: ObjAddr, obj_addrs: ObjAddr,
/// If true, enables debug mode /// If true, enables debug mode
@ -131,7 +137,7 @@ impl ThreadManager {
/// ## Pamameter /// ## Pamameter
/// ///
/// **thread** is the thread to be put on the read list /// **thread** is the thread to be put on the read list
pub fn ready_to_run(&mut self, thread: Rc<RefCell<Thread>>) { pub fn ready_to_run(&mut self, thread: ThreadRef) {
self.ready_list.push(thread); self.ready_list.push(thread);
} }
@ -141,7 +147,7 @@ impl ThreadManager {
/// Thread is removed from the ready list. /// Thread is removed from the ready list.
/// ///
/// **return** Thread thread to be scheduled /// **return** Thread thread to be scheduled
pub fn find_next_to_run(&mut self) -> Option<Rc<RefCell<Thread>>> { pub fn find_next_to_run(&mut self) -> Option<ThreadRef> {
self.ready_list.pop() self.ready_list.pop()
} }
@ -155,7 +161,7 @@ impl ThreadManager {
/// ## Parameter /// ## Parameter
/// ///
/// **next_thread** thread to dispatch to the CPU /// **next_thread** thread to dispatch to the CPU
pub fn switch_to(&mut self, machine: &mut Machine, next_thread: Rc<RefCell<Thread>>) { pub fn switch_to(&mut self, machine: &mut Machine, next_thread: ThreadRef) {
if let Some(old_thread) = self.get_g_current_thread() { if let Some(old_thread) = self.get_g_current_thread() {
let old_thread = old_thread.clone(); let old_thread = old_thread.clone();
self.thread_save_processor_state(machine, old_thread.clone()); self.thread_save_processor_state(machine, old_thread.clone());
@ -175,7 +181,7 @@ impl ThreadManager {
} }
/// Start a thread, attaching it to a process /// Start a thread, attaching it to a process
pub fn start_thread(&mut self, thread: Rc<RefCell<Thread>>, owner: Rc<RefCell<Process>>, func_pc: u64, sp_loc: u64, argument: i64) { pub fn start_thread(&mut self, thread: ThreadRef, owner: Rc<RefCell<Process>>, func_pc: u64, sp_loc: u64, argument: i64) {
let mut thread_m = thread.borrow_mut(); let mut thread_m = thread.borrow_mut();
assert_eq!(thread_m.process, Option::None); assert_eq!(thread_m.process, Option::None);
thread_m.process = Option::Some(Rc::clone(&owner)); thread_m.process = Option::Some(Rc::clone(&owner));
@ -187,7 +193,7 @@ impl ThreadManager {
} }
/// Wait for another thread to finish its execution /// Wait for another thread to finish its execution
pub fn thread_join(&mut self, machine: &mut Machine, waiter: Rc<RefCell<Thread>>, waiting_for: Rc<RefCell<Thread>>) { pub fn thread_join(&mut self, machine: &mut Machine, waiter: ThreadRef, waiting_for: ThreadRef) {
let waiting_for = Rc::clone(&waiting_for); let waiting_for = Rc::clone(&waiting_for);
while self.get_g_alive().contains(&waiting_for) { while self.get_g_alive().contains(&waiting_for) {
self.debug(format!("Joining \"{}\" to \"{}\"", waiter.borrow().get_name(), waiting_for.borrow().get_name())); self.debug(format!("Joining \"{}\" to \"{}\"", waiter.borrow().get_name(), waiting_for.borrow().get_name()));
@ -198,7 +204,7 @@ impl ThreadManager {
/// Relinquish the CPU if any other thread is runnable. /// Relinquish the CPU if any other thread is runnable.
/// ///
/// Cannot use yield as a function name -> reserved name in rust /// Cannot use yield as a function name -> reserved name in rust
pub fn thread_yield(&mut self, machine: &mut Machine, thread: Rc<RefCell<Thread>>) { pub fn thread_yield(&mut self, machine: &mut Machine, thread: ThreadRef) {
let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff); let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff);
self.debug(format!("Yeilding thread: {}", thread.borrow().get_name())); self.debug(format!("Yeilding thread: {}", thread.borrow().get_name()));
@ -212,7 +218,7 @@ impl ThreadManager {
} }
/// Put the thread to sleep and relinquish the processor /// Put the thread to sleep and relinquish the processor
pub fn thread_sleep(&mut self, machine: &mut Machine, thread: Rc<RefCell<Thread>>) { pub fn thread_sleep(&mut self, machine: &mut Machine, thread: ThreadRef) {
debug_assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); debug_assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread);
debug_assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff); debug_assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff);
@ -227,7 +233,7 @@ impl ThreadManager {
} }
/// Finish the execution of the thread and prepare its deallocation /// Finish the execution of the thread and prepare its deallocation
pub fn thread_finish(&mut self, machine: &mut Machine, thread: Rc<RefCell<Thread>>) { pub fn thread_finish(&mut self, machine: &mut Machine, thread: ThreadRef) {
let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff);
assert!(self.g_alive.remove(Rc::clone(&thread))); assert!(self.g_alive.remove(Rc::clone(&thread)));
self.debug(format!("Sleeping thread {}", thread.borrow().get_name())); self.debug(format!("Sleeping thread {}", thread.borrow().get_name()));
@ -237,7 +243,7 @@ impl ThreadManager {
} }
/// Save the CPU state of a user program on a context switch. /// Save the CPU state of a user program on a context switch.
pub fn thread_save_processor_state(&mut self, machine: &mut Machine, thread: Rc<RefCell<Thread>>) { pub fn thread_save_processor_state(&mut self, machine: &mut Machine, thread: ThreadRef) {
let mut t = thread.borrow_mut(); let mut t = thread.borrow_mut();
for i in 0..NUM_INT_REGS { for i in 0..NUM_INT_REGS {
t.thread_context.int_registers[i] = machine.read_int_register(i); t.thread_context.int_registers[i] = machine.read_int_register(i);
@ -249,7 +255,7 @@ impl ThreadManager {
} }
/// Restore the CPU state of a user program on a context switch. /// Restore the CPU state of a user program on a context switch.
pub fn thread_restore_processor_state(&self, machine: &mut Machine, thread: Rc<RefCell<Thread>>) { pub fn thread_restore_processor_state(&self, machine: &mut Machine, thread: ThreadRef) {
let t: Ref<_> = thread.borrow(); let t: Ref<_> = thread.borrow();
for i in 0..NUM_INT_REGS { for i in 0..NUM_INT_REGS {
machine.write_int_register(i, t.thread_context.int_registers[i]); machine.write_int_register(i, t.thread_context.int_registers[i]);
@ -372,17 +378,17 @@ impl ThreadManager {
} }
/// Currently running thread /// Currently running thread
pub fn get_g_current_thread(&mut self) -> &Option<Rc<RefCell<Thread>>> { pub fn get_g_current_thread(&mut self) -> &Option<ThreadRef> {
&self.g_current_thread &self.g_current_thread
} }
/// List of alive threads /// List of alive threads
pub fn get_g_alive(&mut self) -> &mut List<Rc<RefCell<Thread>>> { pub fn get_g_alive(&mut self) -> &mut List<ThreadRef> {
&mut self.g_alive &mut self.g_alive
} }
/// Set currently running thread /// Set currently running thread
pub fn set_g_current_thread(&mut self, thread: Option<Rc<RefCell<Thread>>>) { pub fn set_g_current_thread(&mut self, thread: Option<ThreadRef>) {
self.g_current_thread = thread self.g_current_thread = thread
} }