From 8732a6f0b7e939d6453f9afac776705f1bec8cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 21 Apr 2023 14:26:02 +0200 Subject: [PATCH 01/19] Added build.rs script - Executes make all - Moves the project logo to the documentation folder --- build.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 build.rs diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..900ea8c --- /dev/null +++ b/build.rs @@ -0,0 +1,26 @@ +//! Build script for BurritOS. +//! +//! Moves files from the assets folder to the target directory +//! and runs `make all`. + +use std::process::Command; + +fn main() { + let mut make_all = Command::new("make"); + make_all.arg("all"); + println!("{:?}", make_all.output().unwrap()); + + let mut create_target_folder = Command::new("mkdir"); + create_target_folder.args([ + "-p", + "target/doc/burritos/assets/" + ]); + println!("{:?}", create_target_folder.output().unwrap()); + + let mut copy_logo = Command::new("cp"); + copy_logo.args([ + "assets/logo/logo.svg", + "target/doc/burritos/assets/logo.svg" + ]); + println!("{:?}", copy_logo.output().unwrap()); +} \ No newline at end of file From f06f14354a6c7cf15cc3b9093a37e3587b56328a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 21 Apr 2023 14:29:00 +0200 Subject: [PATCH 02/19] Added project logo to doc --- src/main.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 61529e7..95a2d69 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ - +#![doc(html_logo_url = "assets/logo.svg", html_favicon_url = "assets/logo.svg")] #![warn(missing_docs)] #![warn(clippy::missing_docs_in_private_items)] @@ -7,10 +7,8 @@ //! Burritos is an educational operating system written in Rust //! running on RISC-V emulator. -/// Contain hardware simulated part of the machine mod simulator; 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}; From 052b950ca0ddb7e5261c7d7bc105a638b5cede1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 21 Apr 2023 14:39:49 +0200 Subject: [PATCH 03/19] :memo: Updated cfg.rs documentation --- src/utility/cfg.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/utility/cfg.rs b/src/utility/cfg.rs index f12e51f..69ba6d1 100644 --- a/src/utility/cfg.rs +++ b/src/utility/cfg.rs @@ -93,7 +93,6 @@ pub fn read_settings() -> Result { } /// Returns a mock configuration for Machine unit testing -/// FIXME: Does not cover the whole configuration yet pub fn get_debug_configuration() -> Settings { let mut settings_map = Settings::new(); settings_map.insert(MachineSettingKey::PageSize, 128); @@ -101,16 +100,23 @@ pub fn get_debug_configuration() -> Settings { settings_map } +/// Filters out empty lines and comments from the reader `BufReader`. +/// +/// Returns a [`Vec`], each entry containing a valid +/// line from the input file. fn filter_garbage(reader: BufReader) -> Vec { reader.lines() .map(|l| l.unwrap()) - .filter(|l| !l.is_empty() && !l.starts_with("#")) + .filter(|l| !l.is_empty() && !l.starts_with('#')) .collect() } +/// Adds a pair to a [`Settings`] map. +/// +/// Returns the updated [`Settings`]. fn update_settings_map(mut settings_map: Settings, key: &str, setting: &str) -> Settings { let key = MachineSettingKey::from(key); - let setting = u64::from_str_radix(setting, 10).unwrap_or(0); + let setting = str::parse::(setting).unwrap_or(0); settings_map.insert(key, setting); settings_map } \ No newline at end of file From 33cbe771750fc6db54f33334e9926305e06e11e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 21 Apr 2023 14:46:06 +0200 Subject: [PATCH 04/19] Fixed logo now showing up in doc --- build.rs | 4 ++-- src/main.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.rs b/build.rs index 900ea8c..2ae1953 100644 --- a/build.rs +++ b/build.rs @@ -13,14 +13,14 @@ fn main() { let mut create_target_folder = Command::new("mkdir"); create_target_folder.args([ "-p", - "target/doc/burritos/assets/" + "target/doc/assets/" ]); println!("{:?}", create_target_folder.output().unwrap()); let mut copy_logo = Command::new("cp"); copy_logo.args([ "assets/logo/logo.svg", - "target/doc/burritos/assets/logo.svg" + "target/doc/assets/logo.svg" ]); println!("{:?}", copy_logo.output().unwrap()); } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 95a2d69..9bf8a0d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -#![doc(html_logo_url = "assets/logo.svg", html_favicon_url = "assets/logo.svg")] +#![doc(html_logo_url = "../assets/logo.svg", html_favicon_url = "../assets/logo.svg")] #![warn(missing_docs)] #![warn(clippy::missing_docs_in_private_items)] From ce4c7230f996fb37d0aea80fc1bf1005b0166fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 21 Apr 2023 14:50:55 +0200 Subject: [PATCH 05/19] :memo: Updated utility mod documentation --- src/utility/mod.rs | 3 +++ src/utility/objaddr.rs | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/utility/mod.rs b/src/utility/mod.rs index c6db391..85e59cc 100644 --- a/src/utility/mod.rs +++ b/src/utility/mod.rs @@ -1,3 +1,6 @@ +//! This module contains data type definitions used in other parts the BurritOS +//! They are separated from the rest of the operating system so as to promote +//! reusability and to separate data constructs proper from state and actions. pub mod list; pub mod objaddr; pub mod cfg; \ No newline at end of file diff --git a/src/utility/objaddr.rs b/src/utility/objaddr.rs index 42ad0a5..b2847e6 100644 --- a/src/utility/objaddr.rs +++ b/src/utility/objaddr.rs @@ -17,9 +17,13 @@ use crate::kernel::{synch::{ Semaphore, Lock }, thread::Thread}; /// calls. #[derive(PartialEq)] pub struct ObjAddr { + /// Id of the last added object last_id: i32, + /// List of [Semaphore] added in this struct. Each is keyed with a unique i32 id. semaphores: HashMap, + /// List of [Lock] added in this struct. Each is keyed with a unique i32 id. locks: HashMap, + /// List of threads known by this instance of ObjAddr (useful for managing lock ownership) threads: HashMap>>, } From ff921117f7aa8d49165c32a87ded39cd1d79f270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 21 Apr 2023 14:55:07 +0200 Subject: [PATCH 06/19] Using direct link to git hosted logo for documentation --- build.rs | 14 -------------- src/main.rs | 5 ++++- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/build.rs b/build.rs index 2ae1953..e3660e1 100644 --- a/build.rs +++ b/build.rs @@ -9,18 +9,4 @@ fn main() { let mut make_all = Command::new("make"); make_all.arg("all"); println!("{:?}", make_all.output().unwrap()); - - let mut create_target_folder = Command::new("mkdir"); - create_target_folder.args([ - "-p", - "target/doc/assets/" - ]); - println!("{:?}", create_target_folder.output().unwrap()); - - let mut copy_logo = Command::new("cp"); - copy_logo.args([ - "assets/logo/logo.svg", - "target/doc/assets/logo.svg" - ]); - println!("{:?}", copy_logo.output().unwrap()); } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 9bf8a0d..9de0c09 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,7 @@ -#![doc(html_logo_url = "../assets/logo.svg", html_favicon_url = "../assets/logo.svg")] +#![doc( + html_logo_url = "https://gitlab.istic.univ-rennes1.fr/simpleos/burritos/-/raw/main/assets/logo/logo.svg", + html_favicon_url = "https://gitlab.istic.univ-rennes1.fr/simpleos/burritos/-/raw/main/assets/logo/logo.svg") +] #![warn(missing_docs)] #![warn(clippy::missing_docs_in_private_items)] From 5393c6e3f2369f9e858d1c65cee874440d8c6fbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Rativel?= Date: Thu, 20 Apr 2023 15:20:28 +0200 Subject: [PATCH 07/19] test lock for multiple threads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Rativel --- src/kernel/thread_manager.rs | 49 +++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 962b3f4..2de0449 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -443,7 +443,7 @@ mod test { } #[test] - fn test_lock(){ + fn test_lock_single(){ let mut machine = Machine::new(true, get_debug_configuration()); let mut thread_manager = ThreadManager::new(true); let lock = Lock::new(); @@ -470,6 +470,53 @@ mod test { } } + #[test] + fn test_lock_multiple() { + let mut machine = Machine::new(true, get_debug_configuration()); + let mut thread_manager = ThreadManager::new(true); + let lock = Lock::new(); + let lock_id = thread_manager.get_obj_addrs().add_lock(lock); + let thread_1 = Rc::new(RefCell::new(Thread::new("test_lock_1"))); + let thread_2 = Rc::new(RefCell::new(Thread::new("test_lock_2"))); + let thread_test_1 = thread_1.clone(); + let thread_test_2 = thread_2.clone(); + thread_manager.ready_to_run(Rc::clone(&thread_1)); + thread_manager.ready_to_run(Rc::clone(&thread_2)); + thread_manager.set_g_current_thread(Some(thread_1)); + + thread_manager.lock_acquire(lock_id, &mut machine).expect("lock acquire return an error at first iteration: "); + { + let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); + assert_eq!(lock.owner,Some(thread_test_1.clone())); + assert!(!lock.free); + assert!(lock.waiting_queue.is_empty()); + } + + thread_manager.set_g_current_thread(Some(thread_2)); + thread_manager.lock_acquire(lock_id, &mut machine).expect("lock acquire return an error at second iteration: "); + { + let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); + assert_eq!(lock.owner,Some(thread_test_1)); + assert!(!lock.free); + assert_eq!(lock.waiting_queue.iter().count(),1); + } + thread_manager.lock_release(lock_id, &mut machine).expect("lock release return an error at first iteration: "); + { + let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); + assert_eq!(lock.owner, Some(thread_test_2)); + assert!(!lock.free); + assert!(lock.waiting_queue.is_empty()); + } + thread_manager.lock_release(lock_id, &mut machine).expect("lock release return an error at second iteration: "); + { + let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); + assert_eq!(lock.owner, None); + assert!(lock.free); + assert!(lock.waiting_queue.is_empty()); + } + } + + #[test] fn test_semaphore_single() { // Init From f6195a9da0f8d7152505150f73c9edd3c06be982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Thu, 20 Apr 2023 15:15:11 +0200 Subject: [PATCH 08/19] Updated thread_manager module documentation --- src/kernel/thread_manager.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 2de0449..654f4e8 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -1,13 +1,15 @@ //! # Thread manager //! //! This module describes the data structure and the methods used for thread scheduling -//! in the BurritOS operating system. A struct named `ThreadManager` holds the list of -//! all existing threads and synchronization objects, such as `Locks`, `Semaphores` and -//! `Conditions`. +//! in the BurritOS operating system. A struct named [`ThreadManager`] holds the list of +//! all existing [`Thread`] instances and synchronization objects, such as +//! [`Lock`](crate::kernel::synch::Lock), +//! [`Semaphore`](crate::kernel::synch::Semaphore) and +//! [`Condition`](crate::kernel::synch::Condition). //! //! ## Purpose //! -//! `ThreadManager` holds the state of the system processes using the following subcomponents: +//! [`ThreadManager`] holds the state of the system processes using the following subcomponents: //! //! ### Two lists of threads //! @@ -24,21 +26,23 @@ //! //! Locks, Semaphores and Conditions allow resource sharing among running threads. Since resources //! can only be accessed by a single thread at a time, we need data structures to signal other -//! threads that a resource may be busy or unavailable; say for example that thread **A** wants to -//! write to a file while **B** is currently reading said file. Thread **A** mutating the state of -//! the file could cause issues for **B**. Therefore **B** needs to lock the file in question to -//! avoid such issues. Thread **A** will have to wait for **B** to finish reading the file. +//! threads that a resource may be busy or unavailable; say for example that: +//! +//! - Thread **A** wants to write to a file while **B** is currently reading said file. +//! - Thread **A** mutating the state of the file could cause issues for **B**. +//! - Therefore **B** needs to lock the file in question to avoid such issues. +//! - Thread **A** will have to wait for **B** to finish reading the file. //! //! These synchronization objects are held in an instance of the ObjAddr structure held by //! ThreadManager. Their state is mutated depending on the actions of the currently running thread -//! through methods such as `ThreadManager::sem_p`. +//! through methods such as [`ThreadManager::sem_p`]. //! //! ## Usage //! -//! `ThreadManager` is thought as a subcomponent of the `System` struct. Instanciating -//! `System` will automatically instanciate a `ThreadManager` +//! [`ThreadManager`] is thought as a subcomponent of the [`System`](crate::kernel::system::System) struct. +//! Instanciating [`System`](crate::kernel::system::System) will automatically instanciate a [`ThreadManager`] //! -//! Manually loading a Thread into ThreadManager to execute a program with BurritOS could look like +//! Manually loading a [`Thread`] into [`ThreadManager`] to execute a program with BurritOS could look like //! this: //! //! ``` @@ -62,8 +66,8 @@ //! //! ## Imports //! -//! The `List` and `ObjAddr` submodules used in this module are defined in the utility -//! module. The source code of ObjAddr has been decoupled from thread_manager in an effort +//! The [`List`] and [`ObjAddr`] submodules used in this module are defined in the utility +//! module. The source code of [`ObjAddr`] has been decoupled from thread_manager in an effort //! to keep this module concise. use std::{ From 31f1e760e9123a5223b94ced3c744bdd32f25ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Thu, 20 Apr 2023 15:34:49 +0200 Subject: [PATCH 09/19] Fixed lock_release behaviour when multiple users of given lock --- src/kernel/thread_manager.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 654f4e8..c6cd396 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -367,14 +367,14 @@ impl ThreadManager { if let Some(lock_owner) = &lock.owner { if Rc::ptr_eq(¤t_thread, lock_owner) { if let Some(thread) = lock.waiting_queue.pop() { + if !lock.waiting_queue.is_empty() { let clone = Rc::clone(&thread); lock.owner = Some(thread); self.ready_to_run(clone); - lock.free = true; } else { lock.free = true; lock.owner = None; - } + }} } }; self.get_obj_addrs().update_lock(id, lock); @@ -514,9 +514,9 @@ mod test { thread_manager.lock_release(lock_id, &mut machine).expect("lock release return an error at second iteration: "); { let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); + assert!(lock.waiting_queue.is_empty()); assert_eq!(lock.owner, None); assert!(lock.free); - assert!(lock.waiting_queue.is_empty()); } } From c6f5818059b77e426314e8c16df1da4428a1a2ca Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Sun, 23 Apr 2023 15:11:06 +0200 Subject: [PATCH 10/19] try to implement join --- src/kernel/exception.rs | 6 ++---- src/kernel/thread.rs | 11 +++++------ src/kernel/thread_manager.rs | 30 +++++++++++++++++++++--------- src/main.rs | 18 +++++++++++------- src/simulator/machine.rs | 2 +- src/utility/list.rs | 5 ++--- test/syscall_tests/Makefile | 2 +- test/syscall_tests/join.c | 36 ++++++++++++++++++++++++++++++++++++ 8 files changed, 79 insertions(+), 31 deletions(-) create mode 100644 test/syscall_tests/join.c diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index f90f271..45fb0c1 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -278,7 +278,7 @@ fn sc_new_thread(machine: &mut Machine, system: &mut System) -> Result usize { let mut c = 1; while c != 0 { c = machine.read_memory(1, addr + i); - i +=1; + i += 1; } - println!("addr: {:x}, i: {}", addr, i + 1); i + 1 } @@ -334,7 +333,6 @@ fn get_string_param(addr: usize, maxlen: usize, machine: &Machine) -> Vec dest.push(c as char); i += 1; } - dest.push('\0'); dest } diff --git a/src/kernel/thread.rs b/src/kernel/thread.rs index 838a5de..d0bdc3e 100644 --- a/src/kernel/thread.rs +++ b/src/kernel/thread.rs @@ -1,7 +1,7 @@ use std::{rc::Rc, cell::RefCell}; -use super::process::Process; -use crate::{simulator::machine::{NUM_INT_REGS, NUM_FP_REGS, STACK_REG}}; +use super::{process::Process, thread_manager::ThreadRef}; +use crate::{simulator::machine::{NUM_INT_REGS, NUM_FP_REGS, STACK_REG}, utility::list::List}; const STACK_FENCEPOST: u32 = 0xdeadbeef; @@ -26,7 +26,7 @@ pub struct Thread { name: String, pub process: Option>>, pub thread_context: ThreadContext, - pub stack_pointer: i32, + pub join_thread: List, } impl Thread { @@ -40,9 +40,9 @@ impl Thread { thread_context: ThreadContext { int_registers: [0; NUM_INT_REGS], float_registers: [0f32; NUM_FP_REGS], - pc: 0 + pc: 0, }, - stack_pointer: 0, + join_thread: List::default(), } } @@ -94,7 +94,6 @@ mod test { float_registers: [0f32; NUM_FP_REGS], pc: 0 }; - x.stack_pointer = 0; x } }; } diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index c6cd396..82faf87 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -102,7 +102,7 @@ use crate::{ }; /// Using this type alias to simplify struct and method definitions -type ThreadRef = Rc>; +pub type ThreadRef = Rc>; /// # Thread manager /// @@ -186,6 +186,8 @@ impl ThreadManager { /// Start a thread, attaching it to a process pub fn start_thread(&mut self, thread: ThreadRef, owner: Rc>, func_pc: u64, sp_loc: u64, argument: i64) { + self.debug(format!("starting thread \"{}\"", thread.borrow().get_name())); + let mut thread_m = thread.borrow_mut(); assert_eq!(thread_m.process, Option::None); thread_m.process = Option::Some(Rc::clone(&owner)); @@ -199,23 +201,29 @@ impl ThreadManager { /// Wait for another thread to finish its execution pub fn thread_join(&mut self, machine: &mut Machine, waiter: ThreadRef, waiting_for: ThreadRef) { let waiting_for = Rc::clone(&waiting_for); - while self.get_g_alive().contains(&waiting_for) { - self.debug(format!("Joining \"{}\" to \"{}\"", waiter.borrow().get_name(), waiting_for.borrow().get_name())); - self.thread_yield(machine, Rc::clone(&waiter)); + if self.get_g_alive().contains(&waiting_for) { + waiting_for.borrow_mut().join_thread.push(Rc::clone(&waiter)); + self.thread_yield(machine, Rc::clone(&waiter), false); } } /// Relinquish the CPU if any other thread is runnable. /// /// Cannot use yield as a function name -> reserved name in rust - pub fn thread_yield(&mut self, machine: &mut Machine, thread: ThreadRef) { + /// + /// ## Parameters + /// + /// **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); - self.debug(format!("Yeilding thread: {}", thread.borrow().get_name())); + self.debug(format!("Yeilding thread: \"{}\"", thread.borrow().get_name())); debug_assert_eq!(&Option::Some(Rc::clone(&thread)), self.get_g_current_thread()); let next_thread = self.find_next_to_run(); if let Some(next_thread) = next_thread { - self.ready_to_run(thread); + if is_ready { + self.ready_to_run(thread); + } self.switch_to(machine, next_thread); } machine.interrupt.set_status(old_status); @@ -226,6 +234,7 @@ impl ThreadManager { debug_assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread); debug_assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff); + self.debug(format!("Sleeping thread {}", thread.borrow().get_name())); let mut next_thread = self.find_next_to_run(); while next_thread.is_none() { eprintln!("Nobody to run => idle"); @@ -240,8 +249,11 @@ impl ThreadManager { pub fn thread_finish(&mut self, machine: &mut Machine, thread: ThreadRef) { let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); assert!(self.g_alive.remove(Rc::clone(&thread))); - self.debug(format!("Sleeping thread {}", thread.borrow().get_name())); + self.debug(format!("Finishing thread {}", thread.borrow().get_name())); // g_objets_addrs->removeObject(self.thread) // a ajouté plus tard + for (_, el) in thread.borrow().join_thread.iter().enumerate() { + self.ready_to_run(Rc::clone(&el)); + } self.thread_sleep(machine, Rc::clone(&thread)); machine.interrupt.set_status(old_status); } @@ -432,7 +444,7 @@ mod test { let owner1 = Process { num_thread: 0 }; let owner1 = Rc::new(RefCell::new(owner1)); - system.get_thread_manager().start_thread(Rc::clone(&thread1), owner1, loader.elf_header.entrypoint, ptr, -1); + system.get_thread_manager().start_thread(Rc::clone(&thread1), owner1, loader.elf_header.entrypoint, ptr + machine.page_size, -1); debug_assert_eq!(thread1.borrow_mut().thread_context.pc, start_pc); debug_assert!(system.get_thread_manager().get_g_alive().contains(&Rc::clone(&thread1))); diff --git a/src/main.rs b/src/main.rs index 9de0c09..4b701dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,7 @@ use simulator::{machine::Machine, loader}; use clap::Parser; -use utility::cfg::{get_debug_configuration, read_settings}; +use utility::cfg::read_settings; #[derive(Parser, Debug)] #[command(name = "BurritOS", author, version, about = "Burritos (BurritOS Using Rust Really Improves The Operating System) @@ -30,9 +30,13 @@ Burritos is an educational operating system written in Rust running on RISC-V emulator.", long_about = None)] /// Launch argument parser struct Args { - /// Enable debug mode - #[arg(short, long)] - debug: bool, + /// Enable debug mode. + /// 0 to disable debug, + /// 1 to enable machine debug, + /// 2 to enable system debug, + /// 3 to enable all debug + #[arg(short, long, value_parser = clap::value_parser!(u8).range(0..=3))] + debug: u8, /// Path to the executable binary file to execute #[arg(short = 'x', long, value_name = "PATH")] executable: String @@ -41,10 +45,10 @@ struct Args { fn main() { let args = Args::parse(); - let mut machine = Machine::new(args.debug, read_settings().unwrap()); + let mut machine = Machine::new(args.debug & 1 != 0, read_settings().unwrap()); let (loader, ptr) = loader::Loader::new(args.executable.as_str(), &mut machine, 0).expect("An error occured while parsing the program"); - let mut system = System::new(args.debug); + let mut system = System::new(args.debug & 2 != 0); let thread_exec = Thread::new(args.executable.as_str()); let thread_exec = Rc::new(RefCell::new(thread_exec)); @@ -52,7 +56,7 @@ fn main() { let owner1 = Process { num_thread: 0 }; let owner1 = Rc::new(RefCell::new(owner1)); - system.get_thread_manager().start_thread(Rc::clone(&thread_exec), owner1, loader.elf_header.entrypoint, ptr, -1); + system.get_thread_manager().start_thread(Rc::clone(&thread_exec), owner1, loader.elf_header.entrypoint, ptr + machine.page_size, -1); let to_run = system.get_thread_manager().find_next_to_run().unwrap(); system.get_thread_manager().switch_to(&mut machine, Rc::clone(&to_run)); diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 040da76..fae3a68 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -95,7 +95,7 @@ pub struct Machine { // futur taille à calculer int memSize = g_cfg->NumPhysPages * g_cfg->PageSize; //creer une struct cfg(configuration) qui s'initialise avec valeur dans un fichier cfg num_phy_page: u64, - page_size: u64, + pub page_size: u64, /// Current machine status pub status: MachineStatus } diff --git a/src/utility/list.rs b/src/utility/list.rs index 7a90d0a..0334261 100644 --- a/src/utility/list.rs +++ b/src/utility/list.rs @@ -9,11 +9,10 @@ use std::ptr; /// These methods wrap unsafe instructions because it doesn't respect borrow rules per example /// but everything has been tested with miri to assure there's no Undefined Behaviour (use-after-free, double free, etc.) /// or memory leak -#[derive(PartialEq)] -#[derive(Clone)] +#[derive(PartialEq, Clone, Debug)] pub struct List { head: Link, - tail: *mut Node, + tail: Link, } type Link = *mut Node; diff --git a/test/syscall_tests/Makefile b/test/syscall_tests/Makefile index 8388949..79041ed 100644 --- a/test/syscall_tests/Makefile +++ b/test/syscall_tests/Makefile @@ -1,4 +1,4 @@ -PROGRAMS = halt.guac prints.guac producteur_consommateur.guac +PROGRAMS = halt.guac prints.guac producteur_consommateur.guac join.guac TOPDIR = ../.. include $(TOPDIR)/Makefile.rules diff --git a/test/syscall_tests/join.c b/test/syscall_tests/join.c new file mode 100644 index 0000000..8d26596 --- /dev/null +++ b/test/syscall_tests/join.c @@ -0,0 +1,36 @@ +#include "userlib/syscall.h" +#include "userlib/libnachos.h" + + +const int N = 3; +int iplein = 0; +int ivide = 0; +int tab[3]; +SemId svide; +SemId splein; + +void th1(); + +void th2(); + +int main() { + ThreadId th1 = threadCreate("th1", th1); + ThreadId th2 = threadCreate("th2", th2); + Join(th1); + Join(th2); + return 0; +} + +void th1() { + for(int i = 0; i < 10; i++) + { + n_printf("Hello from th1\n"); + } +} + +void th2() { + for(int i = 0; i < 10; i++) + { + n_printf("Hello from th2\n"); + } +} From 9bd0ef02aaed8b7e3995cc6d7d71552361ce6028 Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Thu, 4 May 2023 22:19:00 +0200 Subject: [PATCH 11/19] Fix join not working on join.c --- src/main.rs | 2 +- test/syscall_tests/join.c | 34 ++++++++++++---------------------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4b701dc..5ff4398 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,7 +35,7 @@ struct Args { /// 1 to enable machine debug, /// 2 to enable system debug, /// 3 to enable all debug - #[arg(short, long, value_parser = clap::value_parser!(u8).range(0..=3))] + #[arg(short, long, value_parser = clap::value_parser!(u8).range(0..=3), default_value_t = 0)] debug: u8, /// Path to the executable binary file to execute #[arg(short = 'x', long, value_name = "PATH")] diff --git a/test/syscall_tests/join.c b/test/syscall_tests/join.c index 8d26596..2466066 100644 --- a/test/syscall_tests/join.c +++ b/test/syscall_tests/join.c @@ -1,36 +1,26 @@ #include "userlib/syscall.h" #include "userlib/libnachos.h" - -const int N = 3; -int iplein = 0; -int ivide = 0; -int tab[3]; -SemId svide; -SemId splein; - -void th1(); - -void th2(); - -int main() { - ThreadId th1 = threadCreate("th1", th1); - ThreadId th2 = threadCreate("th2", th2); - Join(th1); - Join(th2); - return 0; -} - -void th1() { +void thread1() { for(int i = 0; i < 10; i++) { n_printf("Hello from th1\n"); } } -void th2() { +void thread2() { for(int i = 0; i < 10; i++) { n_printf("Hello from th2\n"); } } + + +int main() { + ThreadId th1 = threadCreate("thread 1", thread1); + ThreadId th2 = threadCreate("thread 2", thread2); + Join(th1); + Join(th2); + Shutdown(); + return 0; +} From 9dec9b041abd679f548331a63743a0b268ab2c7f Mon Sep 17 00:00:00 2001 From: Rativel Remi Date: Tue, 2 May 2023 19:57:43 +0000 Subject: [PATCH 12/19] Update userlib/sys.s --- userlib/sys.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/userlib/sys.s b/userlib/sys.s index 7b7e3da..fc3d526 100644 --- a/userlib/sys.s +++ b/userlib/sys.s @@ -1,5 +1,5 @@ /* Start.s - * Assembly language assist for user programs running on top of Nachos. + * Assembly language assist for user programs running on top of BurritOS. * * Since we don't want to pull in the entire C library, we define * what we need for a user program here, namely Start and the system From 7b7d48c775d71f22ade6dbc8e9d8fed626288f84 Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Thu, 4 May 2023 22:58:13 +0200 Subject: [PATCH 13/19] Try to fix double free --- src/kernel/thread_manager.rs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 82faf87..f7858fa 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -367,29 +367,30 @@ impl ThreadManager { /// Wake up a waiter if necessary, or release it if no thread is waiting. pub fn lock_release(&mut self, id: i32, machine: &mut Machine) -> Result { + let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); let current_thread = match self.get_g_current_thread() { Some(thread) => Rc::clone(thread), None => Err(String::from("lock_release error: current_thread should not be None."))? }; - let mut lock = match self.get_obj_addrs().search_lock(id).cloned() { + let mut lock = match self.get_obj_addrs().search_lock(id) { Some(lock) => lock, None => Err(String::from("lock_release error: cannot find lock."))? }; - let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); if let Some(lock_owner) = &lock.owner { - if Rc::ptr_eq(¤t_thread, lock_owner) { - if let Some(thread) = lock.waiting_queue.pop() { - if !lock.waiting_queue.is_empty() { - let clone = Rc::clone(&thread); - lock.owner = Some(thread); - self.ready_to_run(clone); - } else { - lock.free = true; - lock.owner = None; - }} + if current_thread.eq(lock_owner) { // is_held_by_current_thread + match lock.waiting_queue.pop() { + Some(th) => { + lock.owner = Some(Rc::clone(&th)); + self.ready_to_run(Rc::clone(&th)); + }, + None => { + lock.free = true; + lock.owner = None; + } + } } }; - self.get_obj_addrs().update_lock(id, lock); + // self.get_obj_addrs().update_lock(id, lock); machine.interrupt.set_status(old_status); Ok(MachineOk::Ok) } From d35314bead0c476679533f172710ec29c93f73b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Thu, 4 May 2023 23:44:10 +0200 Subject: [PATCH 14/19] Added missing current_thread assignment in test_lock_multiple --- src/kernel/thread_manager.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index f7858fa..e09606e 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -391,6 +391,7 @@ impl ThreadManager { } }; // self.get_obj_addrs().update_lock(id, lock); + machine.interrupt.set_status(old_status); Ok(MachineOk::Ok) } @@ -495,35 +496,36 @@ mod test { let lock_id = thread_manager.get_obj_addrs().add_lock(lock); let thread_1 = Rc::new(RefCell::new(Thread::new("test_lock_1"))); let thread_2 = Rc::new(RefCell::new(Thread::new("test_lock_2"))); - let thread_test_1 = thread_1.clone(); - let thread_test_2 = thread_2.clone(); - thread_manager.ready_to_run(Rc::clone(&thread_1)); - thread_manager.ready_to_run(Rc::clone(&thread_2)); - thread_manager.set_g_current_thread(Some(thread_1)); + thread_manager.ready_to_run(thread_1.clone()); + thread_manager.ready_to_run(thread_2.clone()); + thread_manager.set_g_current_thread(Some(thread_1.clone())); thread_manager.lock_acquire(lock_id, &mut machine).expect("lock acquire return an error at first iteration: "); { let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); - assert_eq!(lock.owner,Some(thread_test_1.clone())); + assert_eq!(lock.owner,Some(thread_1.clone())); assert!(!lock.free); assert!(lock.waiting_queue.is_empty()); } - thread_manager.set_g_current_thread(Some(thread_2)); + thread_manager.set_g_current_thread(Some(thread_2.clone())); thread_manager.lock_acquire(lock_id, &mut machine).expect("lock acquire return an error at second iteration: "); { let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); - assert_eq!(lock.owner,Some(thread_test_1)); + assert_eq!(lock.owner,Some(thread_1.clone())); assert!(!lock.free); assert_eq!(lock.waiting_queue.iter().count(),1); } + thread_manager.lock_release(lock_id, &mut machine).expect("lock release return an error at first iteration: "); { let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); - assert_eq!(lock.owner, Some(thread_test_2)); + assert_eq!(lock.owner, Some(thread_2.clone())); assert!(!lock.free); assert!(lock.waiting_queue.is_empty()); } + + thread_manager.set_g_current_thread(Some(thread_2.clone())); thread_manager.lock_release(lock_id, &mut machine).expect("lock release return an error at second iteration: "); { let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); From 692c3bfa03368e0d158bc4a996db21832a677aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Rativel?= Date: Tue, 9 May 2023 19:15:56 +0200 Subject: [PATCH 15/19] Documentation for mem_cmp.rs and mmu.rs modules --- src/simulator/mem_cmp.rs | 41 ++++++++++++++++++++++++++++------------ src/simulator/mmu.rs | 28 +++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/simulator/mem_cmp.rs b/src/simulator/mem_cmp.rs index 07f48b6..64d5942 100644 --- a/src/simulator/mem_cmp.rs +++ b/src/simulator/mem_cmp.rs @@ -1,14 +1,31 @@ -///! FILE.TXT FORMAT Representing machine memory memory -/// - PC -/// - SP -/// - Section_1 -/// - Section_2 -/// - ... -/// - Section_n -/// -/// Each section is divided in 3 parts, on two lines of text -/// addr SPACE len -/// content +//! # mem_cmp +//! +//! This module contains a MemChecker. +//! +//! It's used to compare state memory obtained after a dump memory from NachOS and BurritOS. +//! +//! This module is used exclusively for testing the instruction simulator. +//! +//! Basic usage: +//! +//! ``` +//! let mut m = Machine::new(true, get_debug_configuration()); +//! let mut MemChecker = mem_cmp::MemChecker::from(get_full_path!("memory", expr)); +//! mem_cmp::MemChecker::fill_memory_from_mem_checker(&MemChecker, &mut m); +//! ``` +//! +//! +//! ! FILE.TXT FORMAT Representing machine memory memory +//! - PC +//! - SP +//! - Section_1 +//! - Section_2 +//! - ... +//! - Section_n +//! +//! Each section is divided in 3 parts, on two lines of text +//! addr SPACE len +//! content use std::{fs, io::{BufRead, BufReader, Lines, Error}}; use crate::Machine; @@ -94,7 +111,7 @@ impl MemChecker{ /// Extract the values of pc, sp and sections /// /// ### Parameter - /// -**path** addr to the file + /// - **path** addr to the file /// /// ### Return /// Mem-checker filled diff --git a/src/simulator/mmu.rs b/src/simulator/mmu.rs index 6436794..1d1d9de 100644 --- a/src/simulator/mmu.rs +++ b/src/simulator/mmu.rs @@ -1,18 +1,38 @@ +//! # mmu +//! +//! This module contains a MMU implementation +//! +//! This part isn't tested and integrated to BurritOS because of the lack of pagination implementation +//! +//! + use crate::simulator::translationtable::*; use crate::simulator::machine::*; +//! # Memory Management Unit +//! An MMU possesses a single reference to a translation table +//! This table is associated to the current process pub struct MMU <'a>{ - /* Un MMU possède une seule référence vers une table des pages à un instant donné - * Cette table est associée au processus courant - * Cette référence peut etre mise a jour par exemple lors d'un switchTo - */ + /// Reference to a page table translationTable : Option<&'a mut TranslationTable>, + /// The number of physique pages numPhyPages : u64, + /// Size of each page pageSize : u64 } impl <'a>MMU <'_>{ + /// Create a MMU with a None reference for the translation table + /// + /// ### Parameters + /// + /// - **numPhyPages** the number of physique pages + /// - **pageSize** the size of a page + /// + /// ### Return + /// + /// MMU with None reference and the value for the number of physical pages and pae size associated fn create(numPhyPages: u64, pageSize: u64) -> MMU <'a>{ MMU { translationTable : None, From 28200ebc04efe2c256cb35826137368aa8d1fe4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Rativel?= Date: Tue, 9 May 2023 19:18:40 +0200 Subject: [PATCH 16/19] small fix in mmu.rs documentation --- src/simulator/mmu.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/simulator/mmu.rs b/src/simulator/mmu.rs index 1d1d9de..b97313d 100644 --- a/src/simulator/mmu.rs +++ b/src/simulator/mmu.rs @@ -9,9 +9,9 @@ use crate::simulator::translationtable::*; use crate::simulator::machine::*; -//! # Memory Management Unit -//! An MMU possesses a single reference to a translation table -//! This table is associated to the current process +/// # Memory Management Unit +/// An MMU possesses a single reference to a translation table +/// This table is associated to the current process pub struct MMU <'a>{ /// Reference to a page table translationTable : Option<&'a mut TranslationTable>, From c60aaa1aaeb0432bea218200b713a9319b83ad4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Rativel?= Date: Tue, 9 May 2023 22:02:22 +0200 Subject: [PATCH 17/19] Documentation for the simulator --- src/simulator/interrupt.rs | 22 +++++++++++++++++++++ src/simulator/loader.rs | 18 ++++++++++++++++- src/simulator/mem_cmp.rs | 2 +- src/simulator/mmu.rs | 4 ++-- src/simulator/translationtable.rs | 32 +++++++++++++++++++++---------- 5 files changed, 64 insertions(+), 14 deletions(-) diff --git a/src/simulator/interrupt.rs b/src/simulator/interrupt.rs index c4be710..fd5ca7f 100644 --- a/src/simulator/interrupt.rs +++ b/src/simulator/interrupt.rs @@ -1,17 +1,38 @@ +//! # Interrupt +//! +//! This module contains an interrupt Handler. +//! The methodes one_trick and idle aren't implemented for now +/// # Interrupt +/// +/// Interrupt Handler #[derive(PartialEq)] pub struct Interrupt { + /// Current Status level: InterruptStatus } impl Interrupt { + /// Interrupt constructor + /// + /// ### Return + /// Interrupt with status Off pub fn new() -> Self { Self { level: InterruptStatus::InterruptOff } } + /// Interrupt setter + /// Change the value of the Interrupt + /// + /// ### Parameters + /// - **self** the interupt handler + /// - **new_status** the new status value + /// + /// ### return + /// The previus status pub fn set_status(&mut self, new_status: InterruptStatus) -> InterruptStatus { let old = self.level; self.level = new_status; @@ -25,6 +46,7 @@ impl Interrupt { todo!(); } + /// Interupt getter pub fn get_status(&self) -> InterruptStatus { self.level } diff --git a/src/simulator/loader.rs b/src/simulator/loader.rs index 18f56fe..2aa8789 100644 --- a/src/simulator/loader.rs +++ b/src/simulator/loader.rs @@ -1,9 +1,25 @@ +//! # Loader +//! +//! This module contains a loader for file section. +//! Following the common standard file format for executable files +//! [ELF (Executable and Linkable Format)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Forma) +//! +//! It's used to charge a programme into the machine from a binary file (.guac files) +//! +//! Basic usage: +//! +//! ``` +//! let args = Args::parse(); +//! let mut machine = Machine::new(args.debug & 1 != 0, read_settings().unwrap()); +//! let (loader, ptr) = loader::Loader::new(args.executable.as_str(), &mut machine, 0).expect("An error occured while parsing the program"); +//! ``` + use crate::Machine; use std::fs; use std::io::Read; /// The elf header defines principes aspects of the binary files, it's place at the start of the file -/// see for more informations +/// see [ELF file Header](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header) for more informations pub struct ElfHeader { /// Defines whether the file is big or little endian /// true correspond to big endian, false otherwise diff --git a/src/simulator/mem_cmp.rs b/src/simulator/mem_cmp.rs index 64d5942..31e5a0f 100644 --- a/src/simulator/mem_cmp.rs +++ b/src/simulator/mem_cmp.rs @@ -1,4 +1,4 @@ -//! # mem_cmp +//! # Memory Comparator //! //! This module contains a MemChecker. //! diff --git a/src/simulator/mmu.rs b/src/simulator/mmu.rs index b97313d..b91ace3 100644 --- a/src/simulator/mmu.rs +++ b/src/simulator/mmu.rs @@ -1,8 +1,8 @@ -//! # mmu +//! # MMU //! //! This module contains a MMU implementation //! -//! This part isn't tested and integrated to BurritOS because of the lack of pagination implementation +//! This part isn't tested nor integrated to BurritOS because of the lack of pagination implementation //! //! diff --git a/src/simulator/translationtable.rs b/src/simulator/translationtable.rs index f0d7091..9dfbaa2 100644 --- a/src/simulator/translationtable.rs +++ b/src/simulator/translationtable.rs @@ -1,23 +1,35 @@ -//Nombre maximum de correspondances dans une table des pages -//Cette donnée devra a terme etre recupérée depuis un fichier de configuration +//! # Translation Table +//! +//! This module implement a trnslation table used for fot the MMU Emulator +//! +//! This part isn't tested nor integrated to BurritOS, +//! but will be useful in the futur when the pagination will be implemented. +//! +//! It contains: +//! - all the setters and getters for translation table +//! - modificaters of table values + + +/// Maximum number in a Page Table +/// For a futur evolution of program, this value should be load from a configuration file const MaxVirtPages : u64 = 200000; - -/* Une table de correspondance propre à un processus -* Une variable de type TranslationTable devra etre possédée par un objet de type Process - */ +/// Translation Table corresponding to a process +/// An iteration of type TranslationTable should be possesses by an oject of type Process pub struct TranslationTable{ - //capacité de cette table <=> nombre de correspondances possibles - //A voir si cette donnée doit etre immuable + /// Table size <=> nb of possible translation pub maxNumPages : u64, - //la table en question - //Vec implemente le trait Index, donc un bon choix + ///The table *Vec impemente Index Trait* pub pageTable : Vec } impl TranslationTable { + /// TranslationTable constructor + /// + /// ### Return + /// TranslationTable with an empty Vector pub fn create() -> TranslationTable { let mut tmp_vec : Vec = Vec::new(); From 2f38edee708745b139d34d372e53b7fb11f99d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Rativel?= Date: Wed, 10 May 2023 08:02:25 +0200 Subject: [PATCH 18/19] Module description --- src/simulator/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/simulator/mod.rs b/src/simulator/mod.rs index f764fbd..03108e1 100644 --- a/src/simulator/mod.rs +++ b/src/simulator/mod.rs @@ -1,3 +1,12 @@ +//! This module implement an Instruction simulator +//! with all the simulated hardware requested to run the Machine : +//! - **MMU** +//! - **Processor** +//! - **RAM** +//! - **Interruption Controler** +//! +//! The disk, the console and the serial coupler aren't implmented for now +//! pub mod machine; pub mod error; pub mod instruction; From e430a62c358918d9332f12a00394f69e891042d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Rativel?= Date: Sun, 14 May 2023 23:51:15 +0200 Subject: [PATCH 19/19] Kernel documentation. Still need to do thread.rs --- src/kernel/exception.rs | 5 +++++ src/kernel/mgerror.rs | 8 ++++++++ src/kernel/mod.rs | 6 ++++++ src/kernel/synch.rs | 29 ++++++++++++++++++++++------- src/kernel/thread.rs | 3 +++ 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index 45fb0c1..4d8cf21 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -1,3 +1,8 @@ +//! # Exceprions +//! +//! This module Enum the constant values of the exceptions. +//! They are used to stop the system to execute some opperation + use std::{cell::RefCell, rc::Rc}; use crate::{simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}}}; diff --git a/src/kernel/mgerror.rs b/src/kernel/mgerror.rs index dfe83c8..751284e 100644 --- a/src/kernel/mgerror.rs +++ b/src/kernel/mgerror.rs @@ -1,3 +1,11 @@ +//! # Error Code +//! +//! This module enumerate the possibles error code who could get in a function +//! +//! **Basic Usage:* +//! +//! Result pub enum ErrorCode { diff --git a/src/kernel/mod.rs b/src/kernel/mod.rs index df9b60d..a072709 100644 --- a/src/kernel/mod.rs +++ b/src/kernel/mod.rs @@ -1,3 +1,9 @@ +//! # Kernel +//! +//! This module contains all the tool required for the kernel to work. +//! +//! Currently it contains the scheduling and synchroisation tools, but it will contains the tools +//! required Memory gestion, Files gestion and peripheral pilots. pub mod process; pub mod thread; pub mod mgerror; diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index a1472e5..2b5cb88 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -1,3 +1,11 @@ +//! # Synchronisation +//! +//! This module contains some scheduling and synchronisation utilities: +//! - **Semaphore** +//! - **Lock** +//! +//! Conditions aren't implemented currently + use crate::utility::list::List; use crate::kernel::thread::Thread; use crate::simulator::interrupt::InterruptStatus::InterruptOff; @@ -6,20 +14,21 @@ use std::cell::RefCell; use std::rc::Rc; use super::thread_manager::ThreadManager; -/// Structure of a Semaphore used for synchronisation +/// Structure of a Semaphore used for synchronisation. +/// It use a counter to determine the number of thread that can be executed simultaneously. #[derive(PartialEq)] pub struct Semaphore { - /// Counter of simultanous Semaphore + /// Counter of simultaneous Semaphore pub counter:i32, - /// QUeue of Semaphore waiting to be exucated + /// QUeue of Semaphore waiting to be executed pub waiting_queue:List>>, } impl Semaphore { - /// Initializes a semaphore, so that it can be used for synchronization. + /// Initializes a semaphore, so that it can be used for synchronization. /// /// ### Parameters /// - *counter* initial value of counter @@ -49,7 +58,7 @@ pub struct Lock { impl Lock { /// Initialize a Lock, so that it can be used for synchronization. - /// The lock is initialy free + /// The lock is initially free /// /// ### Parameters /// - **thread_manager** Thread manager which managing threads @@ -72,7 +81,7 @@ impl Lock { let old_status = machine.interrupt.set_status(InterruptOff); if self.free { self.free = false; - self.owner = Option::Some(match thread_manager.get_g_current_thread() { + self.owner = Some(match thread_manager.get_g_current_thread() { Some(th) => { Rc::clone(&th) }, @@ -128,8 +137,14 @@ impl Lock { machine.interrupt.set_status(old_status); } - /// True if the current thread holds this lock. + /// Say if the lock is held by the current thread /// Useful for checking in Release, and in Condition operations below. + /// ### Parameters + /// - **self** The current lock + /// - **thread-manager** The thread manager present in the system + /// ### Return + /// True if the current thread holds this lock. + pub fn held_by_current_thread(&mut self, thread_manager: &mut ThreadManager) -> bool { match &self.owner { Some(x) => diff --git a/src/kernel/thread.rs b/src/kernel/thread.rs index d0bdc3e..91a4583 100644 --- a/src/kernel/thread.rs +++ b/src/kernel/thread.rs @@ -1,3 +1,6 @@ +//! # Thread +//! +//! use std::{rc::Rc, cell::RefCell}; use super::{process::Process, thread_manager::ThreadRef};