use crate::utility::list::List; use crate::kernel::thread::Thread; use crate::utility::system::{G_CURRENT_THREAD, G_THREAD_TO_BE_DESTROYED}; struct Scheduler { ready_list: List } impl Scheduler { /// Constructor /// /// Initilize the list of ready thread pub fn new() -> Self { Self { ready_list: List::new() } } /// Mark a thread as aready, but not necessarily running yet. /// /// Put it in the ready list, for later scheduling onto the CPU. /// /// ## Pamameter /// /// **thread** is the thread to be put on the read list pub fn ready_to_run(&mut self, thread: Thread) { self.ready_list.push_back(thread); } /// Return the next thread to be scheduled onto the CPU. /// If there are no ready threads, return Option::None /// /// Thread is removed from the ready list. /// /// **return** Thread thread to be scheduled pub fn find_next_to_run(&mut self) -> Option { self.ready_list.pop_back() } /// Dispatch the CPU to next_thread. Save the state of the old thread /// and load the state of the new thread. /// /// We assume the state of the previously running thread has already been changed from running to blocked or ready. /// /// Global variable g_current_thread become next_thread /// /// ## Parameter /// /// **next_thread** thread to dispatch to the CPU pub fn switch_to(&self, next_thread: Thread) { match G_CURRENT_THREAD.write() { Ok(mut current_thread) => { let old_thread = current_thread.as_mut().unwrap(); old_thread.save_processor_state(); old_thread.save_simulator_state(); if old_thread != &next_thread { next_thread.restore_processor_state(); next_thread.restore_simulator_state(); current_thread.replace(next_thread); } match G_THREAD_TO_BE_DESTROYED.write() { Ok(mut thread_to_be_destroyed) => { if thread_to_be_destroyed.is_some() { drop(thread_to_be_destroyed.take()); } }, Err(err) => { panic!("RwLock is poisonned: {}", err); } } }, Err(err) => { panic!("RwLock is poisonned: {}", err); } } } }