Fix scheduler switch_to by making a lot of change(use smart pointers in place of lifetime reference)
This commit is contained in:
parent
39e26e61bb
commit
7de7f2e007
@ -3,12 +3,12 @@ use std::rc::Rc;
|
||||
|
||||
use crate::utility::list::List;
|
||||
use crate::kernel::thread::Thread;
|
||||
|
||||
use super::system::System;
|
||||
use super::thread_manager::ThreadManager;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub struct Scheduler {
|
||||
ready_list: List<Rc<RefCell<Thread>>>
|
||||
ready_list: List<Rc<RefCell<Thread>>>,
|
||||
pub thread_manager: Option<Rc<RefCell<ThreadManager>>>
|
||||
}
|
||||
|
||||
impl Scheduler {
|
||||
@ -18,7 +18,8 @@ impl Scheduler {
|
||||
/// Initilize the list of ready thread
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
ready_list: List::new()
|
||||
ready_list: List::new(),
|
||||
thread_manager: Option::None
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,16 +54,21 @@ impl Scheduler {
|
||||
/// ## Parameter
|
||||
///
|
||||
/// **next_thread** thread to dispatch to the CPU
|
||||
pub fn switch_to(&self, system: &System, next_thread: Rc<RefCell<Thread>>) {
|
||||
/* if let Some(old_thread) = system.get_g_current_thread() {
|
||||
old_thread.save_processor_state();
|
||||
old_thread.save_simulator_state();
|
||||
pub fn switch_to(&mut self, next_thread: Rc<RefCell<Thread>>) {
|
||||
if let Some(tm) = &self.thread_manager {
|
||||
let rc = Rc::clone(&tm);
|
||||
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();
|
||||
|
||||
if old_thread != &next_thread {
|
||||
next_thread.restore_processor_state();
|
||||
next_thread.restore_simulator_state();
|
||||
system.set_g_current_thread(Option::Some(next_thread));
|
||||
rc.borrow_mut().thread_restore_processor_state(Rc::clone(&next_thread));
|
||||
// next_thread.restore_simulator_state();
|
||||
rc.borrow_mut().set_g_current_thread(Option::Some(next_thread));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("thread manager shouldn't be none");
|
||||
}
|
||||
} */
|
||||
}
|
||||
}
|
@ -9,15 +9,15 @@ use std::rc::Rc;
|
||||
use super::scheduler::Scheduler;
|
||||
use super::thread_manager::ThreadManager;
|
||||
|
||||
pub struct Semaphore<'t> {
|
||||
pub struct Semaphore {
|
||||
|
||||
counter:i32,
|
||||
waiting_queue:List<Rc<RefCell<Thread>>>,
|
||||
thread_manager: Rc<RefCell<ThreadManager<'t>>> // On s'assure que le tm vit plus longtemps que les semaphore avec le lifetime
|
||||
thread_manager: Rc<RefCell<ThreadManager>> // On s'assure que le tm vit plus longtemps que les semaphore avec le lifetime
|
||||
|
||||
}
|
||||
|
||||
impl<'t> Semaphore<'_> {
|
||||
impl Semaphore {
|
||||
|
||||
pub fn p(&mut self, current_thread: Rc<RefCell<Thread>>, machine: &mut Machine){
|
||||
let old_status = machine.interrupt.set_status(InterruptOff);
|
||||
@ -39,16 +39,16 @@ impl<'t> Semaphore<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Lock<'t>{
|
||||
pub struct Lock{
|
||||
|
||||
owner: Rc<RefCell<Thread>>,
|
||||
waiting_queue:List<Rc<RefCell<Thread>>>,
|
||||
thread_manager: Rc<RefCell<ThreadManager<'t>>>,
|
||||
thread_manager: Rc<RefCell<ThreadManager>>,
|
||||
free: bool
|
||||
|
||||
}
|
||||
|
||||
impl<'t> Lock<'_> {
|
||||
impl Lock {
|
||||
pub fn acquire(&mut self, machine: &mut Machine, current_thread: Rc<RefCell<Thread>>) {
|
||||
let old_status = machine.interrupt.set_status(InterruptOff);
|
||||
|
||||
@ -83,14 +83,14 @@ impl<'t> Lock<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Condition<'t>{
|
||||
pub struct Condition{
|
||||
|
||||
waiting_queue:List<Rc<RefCell<Thread>>>,
|
||||
thread_manager: Rc<RefCell<ThreadManager<'t>>>,
|
||||
thread_manager: Rc<RefCell<ThreadManager>>,
|
||||
|
||||
}
|
||||
|
||||
impl<'t> Condition<'_> {
|
||||
impl Condition {
|
||||
|
||||
pub fn wait(&mut self, machine: &mut Machine, current_thread: Rc<RefCell<Thread>>) {
|
||||
let old_status = machine.interrupt.set_status(InterruptOff);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::cell::RefCell;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use crate::simulator::machine::Machine;
|
||||
|
||||
@ -15,24 +15,27 @@ use super::thread_manager::ThreadManager;
|
||||
/// - The thread to be destroyed next
|
||||
/// - The scheduler which acts upon these threads
|
||||
#[derive(PartialEq)]
|
||||
pub struct System<'a> {
|
||||
pub struct System {
|
||||
g_machine: RefCell<Machine>,
|
||||
thread_manager: ThreadManager<'a>
|
||||
thread_manager: Rc<RefCell<ThreadManager>>
|
||||
}
|
||||
|
||||
impl<'a> System<'a> {
|
||||
impl System {
|
||||
|
||||
/// System constructor
|
||||
pub fn new(machine: Machine) -> System<'a> {
|
||||
pub fn new(machine: Machine) -> System {
|
||||
Self {
|
||||
g_machine: RefCell::new(machine),
|
||||
thread_manager: ThreadManager::new()
|
||||
thread_manager: Rc::new(RefCell::new(ThreadManager::new()))
|
||||
}
|
||||
}
|
||||
|
||||
/// use thread_manager setter to send it system instance
|
||||
pub fn freeze(&'a mut self) {
|
||||
self.thread_manager.system.set(Option::Some(self));
|
||||
pub fn freeze(this: Rc<RefCell<System>>) {
|
||||
let copy = Rc::clone(&this);
|
||||
let tm = &this.borrow_mut().thread_manager;
|
||||
tm.borrow_mut().system = Option::Some(copy);
|
||||
ThreadManager::freeze(tm);
|
||||
}
|
||||
|
||||
// GETTERS
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::{rc::Rc, cell::{Cell, RefCell, RefMut, Ref}};
|
||||
use std::{rc::Rc, cell::{RefCell, RefMut, Ref}};
|
||||
|
||||
use crate::{utility::list::List, simulator::{machine::{NUM_INT_REGS, NUM_FP_REGS}, interrupt::InterruptStatus}};
|
||||
|
||||
@ -7,15 +7,15 @@ use super::{scheduler::Scheduler, thread::Thread, system::System, mgerror::Error
|
||||
pub const SIMULATORSTACKSIZE: usize = 32 * 1024;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub struct ThreadManager<'a> {
|
||||
pub struct ThreadManager {
|
||||
pub g_current_thread: Option<Rc<RefCell<Thread>>>,
|
||||
pub g_thread_to_be_destroyed: Option<Rc<RefCell<Thread>>>,
|
||||
pub g_alive: List<Rc<RefCell<Thread>>>,
|
||||
pub g_scheduler: Scheduler,
|
||||
pub system: Cell<Option<&'a System<'a>>>
|
||||
pub system: Option<Rc<RefCell<System>>>
|
||||
}
|
||||
|
||||
impl<'a> ThreadManager<'a> {
|
||||
impl ThreadManager {
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
@ -23,10 +23,15 @@ impl<'a> ThreadManager<'a> {
|
||||
g_thread_to_be_destroyed: Option::None,
|
||||
g_alive: List::new(),
|
||||
g_scheduler: Scheduler::new(),
|
||||
system: Cell::new(None)
|
||||
system: Option::None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn freeze(this: &Rc<RefCell<ThreadManager>>) {
|
||||
let copy = Rc::clone(this);
|
||||
this.borrow_mut().g_scheduler.thread_manager = Option::Some(copy);
|
||||
}
|
||||
|
||||
/// Start a thread, attaching it to a process
|
||||
pub fn start_thread(&mut self, thread: Rc<RefCell<Thread>>, owner: Process, func_pc: i64, argument: i64) -> Result<(), ErrorCode> {
|
||||
let mut thread_m = thread.borrow_mut();
|
||||
@ -38,7 +43,7 @@ impl<'a> ThreadManager<'a> {
|
||||
thread_m.init_simulator_context(base_stack_addr);
|
||||
thread_m.process.as_mut().unwrap().num_thread += 1;
|
||||
self.get_g_alive().push(Rc::clone(&thread));
|
||||
self.g_scheduler().ready_to_run(Rc::clone(&thread));
|
||||
self.g_scheduler.ready_to_run(Rc::clone(&thread));
|
||||
Result::Ok(())
|
||||
}
|
||||
|
||||
@ -53,16 +58,17 @@ impl<'a> ThreadManager<'a> {
|
||||
///
|
||||
/// Cannot use yield as a function name -> reserved name in rust
|
||||
pub fn thread_yield(&mut self, thread: Rc<RefCell<Thread>>) {
|
||||
if let Some(system) = self.system.get() {
|
||||
let mut machine = system.get_g_machine().borrow_mut();
|
||||
if let Some(system) = &self.system {
|
||||
let sys = system.borrow_mut();
|
||||
let mut machine = sys.get_g_machine().borrow_mut();
|
||||
let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff);
|
||||
|
||||
assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread);
|
||||
let next_thread = self.g_scheduler().find_next_to_run();
|
||||
let next_thread = self.g_scheduler.find_next_to_run();
|
||||
if let Some(next_thread) = next_thread {
|
||||
let scheduler = self.g_scheduler();
|
||||
let scheduler = &mut self.g_scheduler;
|
||||
scheduler.ready_to_run(thread);
|
||||
scheduler.switch_to(system, next_thread);
|
||||
scheduler.switch_to(next_thread);
|
||||
}
|
||||
machine.interrupt.set_status(old_status);
|
||||
}
|
||||
@ -72,16 +78,17 @@ impl<'a> ThreadManager<'a> {
|
||||
pub fn thread_sleep(&mut self, thread: Rc<RefCell<Thread>>) {
|
||||
|
||||
assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread);
|
||||
if let Some(system) = self.system.get() {
|
||||
let mut machine = system.get_g_machine().borrow_mut();
|
||||
if let Some(system) = &self.system {
|
||||
let sys = system.borrow_mut();
|
||||
let machine = sys.get_g_machine().borrow_mut();
|
||||
assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff);
|
||||
|
||||
let mut next_thread = self.g_scheduler().find_next_to_run();
|
||||
let mut next_thread = self.g_scheduler.find_next_to_run();
|
||||
while next_thread.is_none() {
|
||||
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()));
|
||||
|
||||
}
|
||||
}
|
||||
@ -92,8 +99,9 @@ impl<'a> ThreadManager<'a> {
|
||||
}
|
||||
|
||||
pub fn thread_save_processor_state(&mut self, thread: Rc<RefCell<Thread>>) {
|
||||
if let Some(system) = self.system.get() {
|
||||
if let Some(system) = &self.system {
|
||||
let mut t: RefMut<_> = thread.borrow_mut();
|
||||
let system = system.borrow_mut();
|
||||
for i in 0..NUM_INT_REGS {
|
||||
t.thread_context.int_registers[i] = system.get_g_machine().borrow().read_int_register(i);
|
||||
}
|
||||
@ -106,7 +114,8 @@ impl<'a> ThreadManager<'a> {
|
||||
}
|
||||
|
||||
pub fn thread_restore_processor_state(&self, thread: Rc<RefCell<Thread>>) {
|
||||
if let Some(system) = self.system.get() {
|
||||
if let Some(system) = &self.system {
|
||||
let system = system.borrow_mut();
|
||||
let t: Ref<_> = thread.borrow();
|
||||
for i in 0..NUM_INT_REGS {
|
||||
let machine = system.get_g_machine();
|
||||
@ -135,11 +144,6 @@ impl<'a> ThreadManager<'a> {
|
||||
&mut self.g_alive
|
||||
}
|
||||
|
||||
/// Current scheduler
|
||||
pub fn g_scheduler(&mut self) -> &mut Scheduler {
|
||||
&mut self.g_scheduler
|
||||
}
|
||||
|
||||
/// Set currently running thread
|
||||
pub fn set_g_current_thread(&mut self, thread: Option<Rc<RefCell<Thread>>>) {
|
||||
self.g_current_thread = thread
|
||||
|
@ -13,11 +13,14 @@ mod kernel;
|
||||
/// module containing useful tools which can be use in most part of the OS to ease the development of the OS
|
||||
pub mod utility;
|
||||
|
||||
use std::{rc::Rc, cell::RefCell};
|
||||
|
||||
use kernel::system::System;
|
||||
use simulator::machine::Machine;
|
||||
|
||||
fn main() {
|
||||
let machine = Machine::init_machine();
|
||||
let mut system = System::new(machine);
|
||||
system.freeze();
|
||||
let system = Rc::new(RefCell::new(System::new(machine)));
|
||||
|
||||
System::freeze(system);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user