update synch.rs
This commit is contained in:
parent
1906ec836c
commit
b22b1dea21
@ -3,12 +3,12 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use crate::utility::list::List;
|
use crate::utility::list::List;
|
||||||
use crate::kernel::thread::Thread;
|
use crate::kernel::thread::Thread;
|
||||||
use super::system::System;
|
|
||||||
use super::thread_manager::ThreadManager;
|
use super::thread_manager::ThreadManager;
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub struct Scheduler {
|
pub struct Scheduler {
|
||||||
ready_list: List<Rc<RefCell<Thread>>>
|
ready_list: List<Rc<RefCell<Thread>>>,
|
||||||
|
pub thread_manager: Option<Rc<RefCell<ThreadManager>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scheduler {
|
impl Scheduler {
|
||||||
@ -18,7 +18,8 @@ impl Scheduler {
|
|||||||
/// Initilize the list of ready thread
|
/// Initilize the list of ready thread
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
ready_list: List::new()
|
ready_list: List::new(),
|
||||||
|
thread_manager: Option::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,17 +54,21 @@ impl Scheduler {
|
|||||||
/// ## Parameter
|
/// ## Parameter
|
||||||
///
|
///
|
||||||
/// **next_thread** thread to dispatch to the CPU
|
/// **next_thread** thread to dispatch to the CPU
|
||||||
pub fn switch_to(&mut self, system: &mut System, next_thread: Rc<RefCell<Thread>>) {
|
pub fn switch_to(&mut self, next_thread: Rc<RefCell<Thread>>) {
|
||||||
let thread_manager = system.get_thread_manager();
|
if let Some(tm) = &self.thread_manager {
|
||||||
if let Some(old_thread) = thread_manager.get_g_current_thread() {
|
let rc = Rc::clone(&tm);
|
||||||
thread_manager.thread_save_processor_state(system, Rc::clone(&old_thread));
|
if let Some(old_thread) = tm.borrow_mut().get_g_current_thread() {
|
||||||
|
rc.borrow_mut().thread_save_processor_state(Rc::clone(&old_thread));
|
||||||
// old_thread.save_simulator_state();
|
// old_thread.save_simulator_state();
|
||||||
|
|
||||||
if old_thread != &next_thread {
|
if old_thread != &next_thread {
|
||||||
thread_manager.thread_restore_processor_state(system, Rc::clone(&next_thread));
|
rc.borrow_mut().thread_restore_processor_state(Rc::clone(&next_thread));
|
||||||
// next_thread.restore_simulator_state();
|
// next_thread.restore_simulator_state();
|
||||||
thread_manager.set_g_current_thread(Option::Some(next_thread));
|
rc.borrow_mut().set_g_current_thread(Option::Some(next_thread));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("thread manager shouldn't be none");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,17 +40,22 @@ impl Semaphore {
|
|||||||
/// Note that thread_manager::thread_sleep assumes that interrupts are disabled
|
/// Note that thread_manager::thread_sleep assumes that interrupts are disabled
|
||||||
/// when it is called.
|
/// when it is called.
|
||||||
///
|
///
|
||||||
/// ### Parameters
|
/// ### Parameters TODO Refaire
|
||||||
/// - *current_thread* the current thread
|
/// - *current_thread* the current thread
|
||||||
/// - *machine* the machine where the threads are executed
|
/// - *machine* the machine where the threads are executed
|
||||||
pub fn p(&mut self, current_thread: Rc<RefCell<Thread>>, system: Rc<RefCell<System>>) {
|
pub fn p(&mut self, system: &mut System) {
|
||||||
let old_status = system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(InterruptOff);
|
let old_status = system.get_machine().interrupt.set_status(InterruptOff);
|
||||||
self.counter -= 1;
|
self.counter -= 1;
|
||||||
if self.counter < 0 {
|
if self.counter < 0 {
|
||||||
self.waiting_queue.push(Rc::clone(¤t_thread));
|
match system.get_thread_manager().get_g_current_thread() {
|
||||||
self.thread_manager.borrow_mut().thread_sleep(current_thread);
|
Some(thread) => {
|
||||||
|
self.waiting_queue.push(Rc::clone(thread));
|
||||||
|
system.get_thread_manager().thread_sleep(system, Rc::clone(thread));
|
||||||
|
},
|
||||||
|
None => unreachable!("Current thread should not be None")
|
||||||
}
|
}
|
||||||
system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(old_status);
|
}
|
||||||
|
system.get_machine().interrupt.set_status(old_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increment semaphore value, waking up a waiting thread if any.
|
/// Increment semaphore value, waking up a waiting thread if any.
|
||||||
@ -63,13 +68,13 @@ impl Semaphore {
|
|||||||
/// ### Parameters
|
/// ### Parameters
|
||||||
/// - **machine** the machine where the threads are executed
|
/// - **machine** the machine where the threads are executed
|
||||||
/// - **scheduler** the scheduler which determine which thread to execute
|
/// - **scheduler** the scheduler which determine which thread to execute
|
||||||
pub fn v(&mut self, system: Rc<RefCell<System>>){
|
pub fn v(&mut self, system: &mut System){
|
||||||
let old_status = system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(InterruptOff);
|
let old_status = system.get_machine().interrupt.set_status(InterruptOff);
|
||||||
self.counter += 1;
|
self.counter += 1;
|
||||||
if self.waiting_queue.peek() != None {
|
if self.waiting_queue.peek() != None {
|
||||||
system.borrow_mut().get_thread_manager().borrow_mut().g_scheduler.ready_to_run(self.waiting_queue.pop().unwrap());
|
system.get_thread_manager().g_scheduler.ready_to_run(self.waiting_queue.pop().unwrap());
|
||||||
}
|
}
|
||||||
system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(old_status);
|
system.get_machine().interrupt.set_status(old_status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,23 +116,30 @@ impl Lock {
|
|||||||
/// ### Parameters
|
/// ### Parameters
|
||||||
/// - **current_thread** the current thread
|
/// - **current_thread** the current thread
|
||||||
/// - **machine** the machine where the threads are executed
|
/// - **machine** the machine where the threads are executed
|
||||||
pub fn acquire(&mut self, current_thread: Option<Rc<RefCell<Thread>>>, system: Rc<RefCell<System>>) {
|
pub fn acquire(&mut self, system: &mut System) {
|
||||||
let old_status = system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(InterruptOff);
|
let old_status = system.get_machine().interrupt.set_status(InterruptOff);
|
||||||
|
|
||||||
if self.free {
|
if self.free {
|
||||||
self.free = false;
|
self.free = false;
|
||||||
self.owner = current_thread;
|
self.owner = Option::Some(match system.get_thread_manager().get_g_current_thread() {
|
||||||
} else {
|
Some(th) => {
|
||||||
match current_thread {
|
Rc::clone(th)
|
||||||
Some(x) => {
|
|
||||||
self.waiting_queue.push(Rc::clone(&x));
|
|
||||||
self.thread_manager.borrow_mut().thread_sleep(x)
|
|
||||||
},
|
},
|
||||||
None => ()
|
None => unreachable!()
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let t = system.get_thread_manager().get_g_current_thread();
|
||||||
|
match t {
|
||||||
|
Some(x) => {
|
||||||
|
let x = Rc::clone(x);
|
||||||
|
self.waiting_queue.push(Rc::clone(&x));
|
||||||
|
system.thread_sleep(Rc::clone(&x));
|
||||||
|
},
|
||||||
|
None => unreachable!("Current thread should not be None")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(old_status);
|
system.get_machine().interrupt.set_status(old_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wake up a waiter if necessary, or release it if no thread is waiting.
|
/// Wake up a waiter if necessary, or release it if no thread is waiting.
|
||||||
@ -139,17 +151,16 @@ impl Lock {
|
|||||||
/// ### Parameters
|
/// ### Parameters
|
||||||
/// - **machine** the machine where the code is executed
|
/// - **machine** the machine where the code is executed
|
||||||
/// - **scheduler** the scheduler which determine which thread to execute
|
/// - **scheduler** the scheduler which determine which thread to execute
|
||||||
pub fn release(&mut self, system: Rc<RefCell<System>>, current_thread: Rc<RefCell<Thread>>) {
|
pub fn release(&mut self, system: &mut System) {
|
||||||
let old_status = system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(InterruptOff);
|
let old_status = system.get_machine().interrupt.set_status(InterruptOff);
|
||||||
|
|
||||||
if self.held_by_current_thread(current_thread) {
|
match system.get_thread_manager().get_g_current_thread() {
|
||||||
|
Some(thread) => {
|
||||||
|
if self.held_by_current_thread(system) {
|
||||||
if self.waiting_queue.peek() != None {
|
if self.waiting_queue.peek() != None {
|
||||||
self.owner = Some(self.waiting_queue.pop().unwrap());
|
self.owner = Some(self.waiting_queue.pop().unwrap());
|
||||||
let sys = system.borrow_mut();
|
|
||||||
let tm = sys.get_thread_manager();
|
|
||||||
let scheduler = &mut tm.borrow_mut().g_scheduler;
|
|
||||||
match &self.owner {
|
match &self.owner {
|
||||||
Some(x) => scheduler.ready_to_run(Rc::clone(&x)),
|
Some(x) => system.get_thread_manager().g_scheduler.ready_to_run(Rc::clone(&x)),
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -157,13 +168,20 @@ impl Lock {
|
|||||||
self.owner = None;
|
self.owner = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
system.borrow_mut().get_g_machine().borrow_mut().interrupt.set_status(old_status);
|
None => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn held_by_current_thread(&mut self, current_thread: Rc<RefCell<Thread>>) -> bool {
|
system.get_machine().interrupt.set_status(old_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn held_by_current_thread(&mut self, system: &mut System) -> bool {
|
||||||
match &self.owner {
|
match &self.owner {
|
||||||
Some(x) => Rc::ptr_eq(&x, ¤t_thread),
|
Some(x) =>
|
||||||
|
match system.get_thread_manager().get_g_current_thread() {
|
||||||
|
Some(thread) => Rc::ptr_eq(&x, thread),
|
||||||
|
None => false
|
||||||
|
}
|
||||||
None => false
|
None => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,11 +213,11 @@ impl Condition {
|
|||||||
/// ### Parameters
|
/// ### Parameters
|
||||||
/// - **current_thread** the current thread
|
/// - **current_thread** the current thread
|
||||||
/// - **machine** the machine where threads are executed
|
/// - **machine** the machine where threads are executed
|
||||||
pub fn wait(&mut self, current_thread: Rc<RefCell<Thread>>, machine: &mut Machine) {
|
pub fn wait(&mut self, current_thread: Rc<RefCell<Thread>>, machine: &mut Machine, system: &mut System) {
|
||||||
let old_status = machine.interrupt.set_status(InterruptOff);
|
let old_status = machine.interrupt.set_status(InterruptOff);
|
||||||
|
|
||||||
self.waiting_queue.push(Rc::clone(¤t_thread));
|
self.waiting_queue.push(Rc::clone(¤t_thread));
|
||||||
self.thread_manager.borrow_mut().thread_sleep(current_thread);
|
self.thread_manager.borrow_mut().thread_sleep(system, current_thread);
|
||||||
|
|
||||||
machine.interrupt.set_status(old_status);
|
machine.interrupt.set_status(old_status);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use std::{cell::RefCell, rc::Rc};
|
|||||||
|
|
||||||
use crate::simulator::machine::Machine;
|
use crate::simulator::machine::Machine;
|
||||||
|
|
||||||
use super::thread_manager::ThreadManager;
|
use super::{thread_manager::ThreadManager, thread::Thread};
|
||||||
|
|
||||||
/// This macro properly initializes the system
|
/// This macro properly initializes the system
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
@ -46,17 +46,23 @@ impl System {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets a thread asleep
|
||||||
|
///
|
||||||
|
pub fn thread_sleep(&mut self, thread: Rc<RefCell<Thread>>) {
|
||||||
|
&self.thread_manager.thread_sleep(self, thread);
|
||||||
|
}
|
||||||
|
|
||||||
// GETTERS
|
// GETTERS
|
||||||
|
|
||||||
/// Returns the Machine
|
/// Returns the Machine
|
||||||
///
|
///
|
||||||
/// Useful to access RAM, devices, ...
|
/// Useful to access RAM, devices, ...
|
||||||
pub fn get_machine(&self) -> &Machine {
|
pub fn get_machine(&mut self) -> &mut Machine {
|
||||||
&self.machine
|
&mut self.machine
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_thread_manager(&self) -> &ThreadManager {
|
pub fn get_thread_manager(&mut self) -> &mut ThreadManager {
|
||||||
&self.thread_manager
|
&mut self.thread_manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
|
@ -70,7 +70,7 @@ impl ThreadManager {
|
|||||||
if let Some(next_thread) = next_thread {
|
if let Some(next_thread) = next_thread {
|
||||||
let scheduler = &mut self.g_scheduler;
|
let scheduler = &mut self.g_scheduler;
|
||||||
scheduler.ready_to_run(thread);
|
scheduler.ready_to_run(thread);
|
||||||
scheduler.switch_to(system, next_thread);
|
scheduler.switch_to(next_thread);
|
||||||
}
|
}
|
||||||
machine.interrupt.set_status(old_status);
|
machine.interrupt.set_status(old_status);
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ impl ThreadManager {
|
|||||||
machine.interrupt.idle();
|
machine.interrupt.idle();
|
||||||
next_thread = self.g_scheduler.find_next_to_run();
|
next_thread = self.g_scheduler.find_next_to_run();
|
||||||
}
|
}
|
||||||
self.g_scheduler.switch_to(system, Rc::clone(&next_thread.unwrap()));
|
self.g_scheduler.switch_to(Rc::clone(&next_thread.unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finish the execution of the thread and prepare its deallocation
|
/// Finish the execution of the thread and prepare its deallocation
|
||||||
|
Loading…
Reference in New Issue
Block a user