Merge remote-tracking branch 'origin/thread_scheduler' into thread_scheduler

# Conflicts:
#	src/kernel/synch.rs
This commit is contained in:
Rémi Rativel
2023-03-13 23:41:20 +01:00
27 changed files with 628 additions and 62 deletions

View File

@ -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));
if old_thread != &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");
}
}
}

View File

@ -111,7 +111,7 @@ impl<'t> Lock<'_> {
pub fn release(&mut self, machine: &mut Machine, scheduler: &mut Scheduler, current_thread: Rc<RefCell<Thread>>) {
let old_status = machine.interrupt.set_status(InterruptOff);
if self.held_by_current_thread(current_thread) {
if self.is_held_by_current_thread(current_thread) {
if self.waiting_queue.peek() != None {
self.owner = self.waiting_queue.pop().unwrap();
scheduler.ready_to_run(Rc::clone(&self.owner));
@ -123,7 +123,7 @@ impl<'t> Lock<'_> {
machine.interrupt.set_status(old_status);
}
pub fn held_by_current_thread(&mut self, current_thread: Rc<RefCell<Thread>>) -> bool {
pub fn is_held_by_current_thread(&mut self, current_thread: Rc<RefCell<Thread>>) -> bool {
Rc::ptr_eq(&self.owner, &current_thread)
}
}

View File

@ -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
@ -61,4 +64,26 @@ pub enum ObjectType {
FileType,
ThreadType,
InvalidType
}
#[cfg(test)]
mod tests {
use crate::{System, Machine};
macro_rules! init_system {
() => {{
let m = Machine::init_machine();
init_system!(m)
}};
($a:expr) => {{
System::new($a)
}};
}
#[test]
fn test_init_system() {
init_system!();
}
}

View File

@ -1,21 +1,21 @@
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}};
use crate::{utility::list::List, simulator::{machine::{NUM_INT_REGS, NUM_FP_REGS}, interrupt::InterruptStatus}};
use super::{scheduler::Scheduler, thread::Thread, system::System, mgerror::ErrorCode, process::Process};
pub const SIMULATORSTACKSIZE: usize = 32 * 1024;
#[derive(PartialEq)]
pub struct ThreadManager<'a> {
pub g_current_thread: Option<Thread>,
pub g_thread_to_be_destroyed: Option<Thread>,
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,13 +23,19 @@ 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();
assert_eq!(thread_m.process, Option::None);
thread_m.process = Option::Some(owner);
let ptr = 0; // todo addrspace
thread_m.init_thread_context(func_pc, ptr, argument);
@ -37,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(())
}
@ -52,15 +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);
let next_thread = self.g_scheduler().find_next_to_run();
assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread);
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);
}
@ -68,7 +76,21 @@ impl<'a> ThreadManager<'a> {
/// Put the thread to sleep and relinquish the processor
pub fn thread_sleep(&mut self, thread: Rc<RefCell<Thread>>) {
todo!();
assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread);
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();
while next_thread.is_none() {
machine.interrupt.idle();
next_thread = self.g_scheduler.find_next_to_run();
}
self.g_scheduler.switch_to(Rc::clone(&next_thread.unwrap()));
}
}
/// Finish the execution of the thread and prepare its deallocation
@ -77,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);
}
@ -91,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();
@ -104,14 +128,14 @@ impl<'a> ThreadManager<'a> {
}
/// Currently running thread
pub fn get_g_current_thread(&mut self) -> &mut Option<Thread> {
pub fn get_g_current_thread(&mut self) -> &mut Option<Rc<RefCell<Thread>>> {
&mut self.g_current_thread
}
/// Thread to be destroyed by [...]
///
/// TODO: Finish the comment with the relevant value
pub fn get_g_thread_to_be_destroyed(&mut self) -> &mut Option<Thread> {
pub fn get_g_thread_to_be_destroyed(&mut self) -> &mut Option<Rc<RefCell<Thread>>> {
&mut self.g_thread_to_be_destroyed
}
@ -120,18 +144,13 @@ 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<Thread>) {
pub fn set_g_current_thread(&mut self, thread: Option<Rc<RefCell<Thread>>>) {
self.g_current_thread = thread
}
/// Set thread to be destroyed next
pub fn set_g_thread_to_be_destroyed(&mut self, thread: Option<Thread>) {
pub fn set_g_thread_to_be_destroyed(&mut self, thread: Option<Rc<RefCell<Thread>>>) {
self.g_thread_to_be_destroyed = thread
}