Merge branch 'doc' into 'main'
Add comments to thread_manager See merge request simpleos/burritos!27
This commit is contained in:
commit
905e647dda
@ -119,6 +119,9 @@ pub struct ThreadManager {
|
||||
obj_addrs: ObjAddr,
|
||||
/// If true, enables debug mode
|
||||
debug: bool,
|
||||
/// Temporary field, to be removed when virtual memory will be available to use.
|
||||
///
|
||||
/// A value to know where the next starting thread should have its stack pointer
|
||||
sp_max: u64,
|
||||
}
|
||||
|
||||
@ -136,19 +139,19 @@ impl ThreadManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark a thread as aready, but not necessarily running yet.
|
||||
/// Mark `thread` as ready, 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
|
||||
/// **thread** is the thread to be put on the ready list
|
||||
pub fn ready_to_run(&mut self, thread: ThreadRef) {
|
||||
self.ready_list.push(thread);
|
||||
}
|
||||
|
||||
/// Return the next thread to be scheduled onto the CPU.
|
||||
/// If there are no ready threads, return Option::None
|
||||
/// If there are no ready threads, return `Option::None`
|
||||
///
|
||||
/// Thread is removed from the ready list.
|
||||
///
|
||||
@ -157,12 +160,12 @@ impl ThreadManager {
|
||||
self.ready_list.pop()
|
||||
}
|
||||
|
||||
/// Dispatch the CPU to next_thread. Save the state of the old thread
|
||||
/// 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
|
||||
/// Variable `g_current_thread` become next_thread
|
||||
///
|
||||
/// ## Parameter
|
||||
///
|
||||
@ -187,6 +190,14 @@ impl ThreadManager {
|
||||
}
|
||||
|
||||
/// Start a thread, attaching it to a process
|
||||
///
|
||||
/// ## Parameter
|
||||
///
|
||||
/// **thread** thread to start
|
||||
/// **owner** process owner of thread (after the execution of this method)
|
||||
/// **func_pc** pc the thread
|
||||
/// **sp_loc** stack pointer of the thread, to remove (or move) when mmu will be completed
|
||||
/// **argument** value to be place on register[10]
|
||||
pub fn start_thread(&mut self, thread: ThreadRef, owner: Rc<RefCell<Process>>, func_pc: u64, sp_loc: u64, argument: i64) {
|
||||
self.debug(format!("starting thread \"{}\"", thread.borrow().get_name()));
|
||||
|
||||
@ -201,6 +212,11 @@ impl ThreadManager {
|
||||
}
|
||||
|
||||
/// Wait for another thread to finish its execution
|
||||
///
|
||||
/// If the thread you want to wait doesn't exist (isn't alive), execution will resume.
|
||||
/// Otherwise, CPU is dispatch to next alive thread if any.
|
||||
///
|
||||
/// When the thread you want to join finish, it place the waiting thread (self) in ready list
|
||||
pub fn thread_join(&mut self, machine: &mut Machine, waiter: ThreadRef, waiting_for: ThreadRef) {
|
||||
let waiting_for = Rc::clone(&waiting_for);
|
||||
if self.get_g_alive().contains(&waiting_for) {
|
||||
@ -211,10 +227,19 @@ impl ThreadManager {
|
||||
|
||||
/// Relinquish the CPU if any other thread is runnable.
|
||||
///
|
||||
/// Cannot use yield as a function name -> reserved name in rust
|
||||
/// If so, put the current thread at the end of the ready list, so it'll be re-scheduled in the future.
|
||||
///
|
||||
/// **Returns** immediately if there's no other thread ready or return when the current thread has been switched.
|
||||
///
|
||||
/// Interruptions are disabled during the process, so all the process of looking for a next thread and switching to it is atomic,
|
||||
/// and is place at its old status at the end of the method.
|
||||
///
|
||||
/// Cannot use `yield` as a function name -> reserved name in rust
|
||||
///
|
||||
/// ## Parameters
|
||||
///
|
||||
/// **machine** RISC-V simulator
|
||||
/// **thread** current thread to be relinquish
|
||||
/// **is_ready** true if **thread** should be readded to ready_to_run list, false otherwise. Typically false when joining per example
|
||||
pub fn thread_yield(&mut self, machine: &mut Machine, thread: ThreadRef, is_ready: bool) {
|
||||
let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff);
|
||||
@ -231,7 +256,16 @@ impl ThreadManager {
|
||||
machine.interrupt.set_status(old_status);
|
||||
}
|
||||
|
||||
/// Put the thread to sleep and relinquish the processor
|
||||
/// Put the thread to sleep and relinquish the processor because the current thread is blocked (Semaphore, Lock, Condition) or because it finished its execution
|
||||
///
|
||||
/// Another thread will eventually wake it up and put it back to ready list after it has been unblocked.
|
||||
///
|
||||
/// Behavior now: At the moment, disk isn't fully develop and not integrated to burritos, so if there's no ready thread, then we stop the OS.
|
||||
///
|
||||
/// Behaviour in the future: If there are no threads on the ready list, that means there is no thread to run,
|
||||
/// we assume this is because at least one thread is waiting for I/O [`interrupt`](crate::simulator::interrupt::Interrupt) (the only reason a new thread can become ready at this point).
|
||||
///
|
||||
/// We also assume interruption are already disabled, becuase it's called from a synchronization routine for interrupt should be disabled.
|
||||
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!(machine.interrupt.get_status(), InterruptStatus::InterruptOff);
|
||||
@ -252,6 +286,12 @@ impl ThreadManager {
|
||||
}
|
||||
|
||||
/// Finish the execution of the thread and prepare its deallocation
|
||||
///
|
||||
/// Called by the thread itself when it finish its execution ([`Exit`](super::exception::SC_EXIT) exception).
|
||||
///
|
||||
/// We remove the thread from the alive list, and rustc deallocate the thread itself(behaviour different than Nachos)
|
||||
///
|
||||
/// Interruption are disabled to assume atomicity.
|
||||
pub fn thread_finish(&mut self, machine: &mut Machine, thread: ThreadRef, exit_code: i64) {
|
||||
let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff);
|
||||
assert!(self.g_alive.remove(Rc::clone(&thread)));
|
||||
@ -265,6 +305,8 @@ impl ThreadManager {
|
||||
}
|
||||
|
||||
/// Save the CPU state of a user program on a context switch.
|
||||
///
|
||||
/// Save PC and registers
|
||||
pub fn thread_save_processor_state(&mut self, machine: &mut Machine, thread: ThreadRef) {
|
||||
let mut t = thread.borrow_mut();
|
||||
for i in 0..NUM_INT_REGS {
|
||||
@ -277,6 +319,8 @@ impl ThreadManager {
|
||||
}
|
||||
|
||||
/// Restore the CPU state of a user program on a context switch.
|
||||
///
|
||||
/// Restore PC and registers
|
||||
pub fn thread_restore_processor_state(&self, machine: &mut Machine, thread: ThreadRef) {
|
||||
let t: Ref<_> = thread.borrow();
|
||||
for i in 0..NUM_INT_REGS {
|
||||
@ -371,7 +415,9 @@ impl ThreadManager {
|
||||
Ok(MachineOk::Ok)
|
||||
}
|
||||
|
||||
/// Wake up a waiter if necessary, or release it if no thread is waiting.
|
||||
/// Release lock hold by current thread and wake up a waiter if necessary, placing it on ready list, this thread now hold the lock.
|
||||
///
|
||||
/// If no thread is waiting for the lock, the lock is released
|
||||
pub fn lock_release(&mut self, id: i32, machine: &mut Machine) -> Result<MachineOk, MachineError> {
|
||||
let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff);
|
||||
let current_thread = match self.get_g_current_thread() {
|
||||
@ -402,12 +448,12 @@ impl ThreadManager {
|
||||
Ok(MachineOk::Ok)
|
||||
}
|
||||
|
||||
/// Currently running thread
|
||||
/// Return currently running thread
|
||||
pub fn get_g_current_thread(&mut self) -> &Option<ThreadRef> {
|
||||
&self.g_current_thread
|
||||
}
|
||||
|
||||
/// List of alive threads
|
||||
/// Return list of alive threads
|
||||
pub fn get_g_alive(&mut self) -> &mut List<ThreadRef> {
|
||||
&mut self.g_alive
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user