1 Commits

Author SHA1 Message Date
9b87a0cd83 Cargo clippy fix 2023-05-06 17:59:48 +02:00
16 changed files with 59 additions and 192 deletions

View File

@ -1,14 +1,9 @@
//! # 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 std::{cell::RefCell, rc::Rc};
use crate::{simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}}}; use crate::{simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}}};
use crate::kernel::synch::{Lock, Semaphore}; use crate::kernel::synch::{Lock, Semaphore};
use super::{system::{System, self}, thread::Thread}; use super::{system::{System}, thread::Thread};
/// The halt system call. Stops Burritos. /// The halt system call. Stops Burritos.
pub const SC_SHUTDOWN: u8 = 0; pub const SC_SHUTDOWN: u8 = 0;
@ -244,7 +239,7 @@ fn sc_sem_create(machine: &mut Machine, system: &mut System) -> Result<MachineOk
let size = get_length_param(addr_name, machine); let size = get_length_param(addr_name, machine);
let _name = get_string_param(addr_name, size, machine); let _name = get_string_param(addr_name, size, machine);
match initial_count < 0 { match initial_count < 0 {
true => Err(format!("Initial_count < 0"))?, true => Err("Initial_count < 0".to_string())?,
false => { false => {
let id = system.get_thread_manager().get_obj_addrs().add_semaphore(Semaphore::new(initial_count)); let id = system.get_thread_manager().get_obj_addrs().add_semaphore(Semaphore::new(initial_count));
machine.write_int_register(10, id as i64); machine.write_int_register(10, id as i64);
@ -283,12 +278,12 @@ fn sc_new_thread(machine: &mut Machine, system: &mut System) -> Result<MachineOk
}; };
let current_thread = current_thread.borrow_mut(); let current_thread = current_thread.borrow_mut();
if let Some(process) = current_thread.get_process_owner() { if let Some(process) = current_thread.get_process_owner() {
system.get_thread_manager().start_thread(n_thread, Rc::clone(&process), func as u64, current_thread.thread_context.int_registers[2] as u64 + machine.page_size, args); system.get_thread_manager().start_thread(n_thread, Rc::clone(process), func as u64, current_thread.thread_context.int_registers[2] as u64 + machine.page_size, args);
// TODO changé la valeur de sp quand on supportera les addresses virtuels // TODO changé la valeur de sp quand on supportera les addresses virtuels
machine.write_int_register(10, tid as i64); machine.write_int_register(10, tid as i64);
Ok(MachineOk::Ok) Ok(MachineOk::Ok)
} else { } else {
return Err("Process owner of current thread is none")?; Err("Process owner of current thread is none")?
} }
} }
@ -355,8 +350,8 @@ mod test {
machine.write_int_register(17, SC_SHUTDOWN as i64); // Set type to shutdown machine.write_int_register(17, SC_SHUTDOWN as i64); // Set type to shutdown
// let ecall = Instruction::new(0b000000000000_00000_000_00000_1110011); // let ecall = Instruction::new(0b000000000000_00000_000_00000_1110011);
machine.write_memory(4, 0, 0b000000000000_00000_000_00000_1110011); // ecall machine.write_memory(4, 0, 0b0000_0000_0000_0000_0000_0000_0111_0011); // ecall
machine.write_memory(4, 4, 0b000000001010_00000_000_00001_0010011); // r1 <- 10 machine.write_memory(4, 4, 0b0000_0000_1010_0000_0000_0000_1001_0011); // r1 <- 10
let mut system = System::new(true); let mut system = System::new(true);
machine.run(&mut system); machine.run(&mut system);
// If the machine was stopped with no error, the shutdown worked // If the machine was stopped with no error, the shutdown worked
@ -382,11 +377,11 @@ mod test {
machine.write_int_register(11, 5); // String size machine.write_int_register(11, 5); // String size
machine.write_int_register(12, 1); // Console output machine.write_int_register(12, 1); // Console output
machine.write_memory(4, 0, 0b000000000000_00000_000_00000_1110011); // ecall machine.write_memory(4, 0, 0b0000_0000_0000_0000_0000_0000_0111_0011); // ecall
machine.write_int_register(17, SC_WRITE as i64); // Set type to write machine.write_int_register(17, SC_WRITE as i64); // Set type to write
machine.write_memory(4, 4, 0b000000000000_00000_000_10001_0010011); // r17 <- SC_SHUTDOWN machine.write_memory(4, 4, 0b0000_0000_0000_0000_0000_1000_1001_0011); // r17 <- SC_SHUTDOWN
machine.write_memory(4, 8, 0b000000000000_00000_000_00000_1110011); // ecall machine.write_memory(4, 8, 0b0000_0000_0000_0000_0000_0000_0111_0011); // ecall
let mut system = System::new(true); let mut system = System::new(true);
machine.run(&mut system); machine.run(&mut system);

View File

@ -1,11 +1,3 @@
//! # Error Code
//!
//! This module enumerate the possibles error code who could get in a function
//!
//! **Basic Usage:*
//!
//! Result<YourSuccessStruct, **ErrorCode**
#![allow(unused, clippy::missing_docs_in_private_items)] #![allow(unused, clippy::missing_docs_in_private_items)]
/// Error enum, use it with Result<YourSucessStruct, **ErrorCode**> /// Error enum, use it with Result<YourSucessStruct, **ErrorCode**>
pub enum ErrorCode { pub enum ErrorCode {

View File

@ -1,9 +1,3 @@
//! # 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 process;
pub mod thread; pub mod thread;
pub mod mgerror; pub mod mgerror;

View File

@ -1,5 +1,5 @@
#[derive(PartialEq, Debug)] #[derive(PartialEq, Eq, Debug)]
pub struct Process { pub struct Process {
pub num_thread: usize, pub num_thread: usize,
} }

View File

@ -1,11 +1,3 @@
//! # Synchronisation
//!
//! This module contains some scheduling and synchronisation utilities:
//! - **Semaphore**
//! - **Lock**
//!
//! Conditions aren't implemented currently
use crate::utility::list::List; use crate::utility::list::List;
use crate::kernel::thread::Thread; use crate::kernel::thread::Thread;
use crate::simulator::interrupt::InterruptStatus::InterruptOff; use crate::simulator::interrupt::InterruptStatus::InterruptOff;
@ -14,21 +6,20 @@ use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use super::thread_manager::ThreadManager; 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)] #[derive(PartialEq)]
pub struct Semaphore { pub struct Semaphore {
/// Counter of simultaneous Semaphore /// Counter of simultanous Semaphore
pub counter:i32, pub counter:i32,
/// QUeue of Semaphore waiting to be executed /// QUeue of Semaphore waiting to be exucated
pub waiting_queue:List<Rc<RefCell<Thread>>>, pub waiting_queue:List<Rc<RefCell<Thread>>>,
} }
impl Semaphore { 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 /// ### Parameters
/// - *counter* initial value of counter /// - *counter* initial value of counter
@ -58,7 +49,7 @@ pub struct Lock {
impl Lock { impl Lock {
/// Initialize a Lock, so that it can be used for synchronization. /// Initialize a Lock, so that it can be used for synchronization.
/// The lock is initially free /// The lock is initialy free
/// ///
/// ### Parameters /// ### Parameters
/// - **thread_manager** Thread manager which managing threads /// - **thread_manager** Thread manager which managing threads
@ -81,16 +72,16 @@ impl Lock {
let old_status = machine.interrupt.set_status(InterruptOff); let old_status = machine.interrupt.set_status(InterruptOff);
if self.free { if self.free {
self.free = false; self.free = false;
self.owner = Some(match thread_manager.get_g_current_thread() { self.owner = Option::Some(match thread_manager.get_g_current_thread() {
Some(th) => { Some(th) => {
Rc::clone(&th) Rc::clone(th)
}, },
None => unreachable!() None => unreachable!()
}); });
} else { } else {
match thread_manager.get_g_current_thread() { match thread_manager.get_g_current_thread() {
Some(x) => { Some(x) => {
let x = Rc::clone(&x); let x = Rc::clone(x);
self.waiting_queue.push(Rc::clone(&x)); self.waiting_queue.push(Rc::clone(&x));
thread_manager.thread_sleep(machine, Rc::clone(&x)); thread_manager.thread_sleep(machine, Rc::clone(&x));
}, },
@ -120,7 +111,7 @@ impl Lock {
Some(thread) => { Some(thread) => {
self.owner = Some(thread); self.owner = Some(thread);
match &self.owner { match &self.owner {
Some(x) => thread_manager.ready_to_run(Rc::clone(&x)), Some(x) => thread_manager.ready_to_run(Rc::clone(x)),
None => () None => ()
} }
}, },
@ -137,14 +128,8 @@ impl Lock {
machine.interrupt.set_status(old_status); machine.interrupt.set_status(old_status);
} }
/// Say if the lock is held by the current thread /// True if the current thread holds this lock.
/// Useful for checking in Release, and in Condition operations below. /// 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 { pub fn held_by_current_thread(&mut self, thread_manager: &mut ThreadManager) -> bool {
match &self.owner { match &self.owner {
Some(x) => Some(x) =>

View File

@ -1,6 +1,3 @@
//! # Thread
//!
//!
use std::{rc::Rc, cell::RefCell}; use std::{rc::Rc, cell::RefCell};
use super::{process::Process, thread_manager::ThreadRef}; use super::{process::Process, thread_manager::ThreadRef};

View File

@ -252,7 +252,7 @@ impl ThreadManager {
self.debug(format!("Finishing thread {}", thread.borrow().get_name())); self.debug(format!("Finishing thread {}", thread.borrow().get_name()));
// g_objets_addrs->removeObject(self.thread) // a ajouté plus tard // g_objets_addrs->removeObject(self.thread) // a ajouté plus tard
for (_, el) in thread.borrow().join_thread.iter().enumerate() { for (_, el) in thread.borrow().join_thread.iter().enumerate() {
self.ready_to_run(Rc::clone(&el)); self.ready_to_run(Rc::clone(el));
} }
self.thread_sleep(machine, Rc::clone(&thread)); self.thread_sleep(machine, Rc::clone(&thread));
machine.interrupt.set_status(old_status); machine.interrupt.set_status(old_status);
@ -512,7 +512,7 @@ mod test {
thread_manager.lock_acquire(lock_id, &mut machine).expect("lock acquire return an error at second iteration: "); 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(); let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap();
assert_eq!(lock.owner,Some(thread_1.clone())); assert_eq!(lock.owner,Some(thread_1));
assert!(!lock.free); assert!(!lock.free);
assert_eq!(lock.waiting_queue.iter().count(),1); assert_eq!(lock.waiting_queue.iter().count(),1);
} }
@ -525,7 +525,7 @@ mod test {
assert!(lock.waiting_queue.is_empty()); assert!(lock.waiting_queue.is_empty());
} }
thread_manager.set_g_current_thread(Some(thread_2.clone())); thread_manager.set_g_current_thread(Some(thread_2));
thread_manager.lock_release(lock_id, &mut machine).expect("lock release return an error at second iteration: "); 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(); let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap();

View File

@ -1,38 +1,17 @@
//! # Interrupt
//!
//! This module contains an interrupt Handler.
//! The methodes one_trick and idle aren't implemented for now
/// # Interrupt #[derive(PartialEq, Eq)]
///
/// Interrupt Handler
#[derive(PartialEq)]
pub struct Interrupt { pub struct Interrupt {
/// Current Status
level: InterruptStatus level: InterruptStatus
} }
impl Interrupt { impl Interrupt {
/// Interrupt constructor
///
/// ### Return
/// Interrupt with status Off
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
level: InterruptStatus::InterruptOff 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 { pub fn set_status(&mut self, new_status: InterruptStatus) -> InterruptStatus {
let old = self.level; let old = self.level;
self.level = new_status; self.level = new_status;
@ -42,11 +21,10 @@ impl Interrupt {
old old
} }
fn one_tick(&self, nb_cycle: i32) { fn one_tick(&self, _nb_cycle: i32) {
todo!(); todo!();
} }
/// Interupt getter
pub fn get_status(&self) -> InterruptStatus { pub fn get_status(&self) -> InterruptStatus {
self.level self.level
} }
@ -57,7 +35,7 @@ impl Interrupt {
} }
#[derive(PartialEq, Clone, Copy, Debug)] #[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum InterruptStatus { pub enum InterruptStatus {
InterruptOff, InterruptOff,
InterruptOn InterruptOn

View File

@ -1,25 +1,9 @@
//! # 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 crate::Machine;
use std::fs; use std::fs;
use std::io::Read; use std::io::Read;
/// The elf header defines principes aspects of the binary files, it's place at the start of the file /// The elf header defines principes aspects of the binary files, it's place at the start of the file
/// see [ELF file Header](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header) for more informations /// see <https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header> for more informations
pub struct ElfHeader { pub struct ElfHeader {
/// Defines whether the file is big or little endian /// Defines whether the file is big or little endian
/// true correspond to big endian, false otherwise /// true correspond to big endian, false otherwise
@ -635,7 +619,7 @@ mod test {
assert_eq!(loader.sections[1].virt_addr, 0x4000); assert_eq!(loader.sections[1].virt_addr, 0x4000);
assert_eq!(loader.sections[1].image_offset, 0x1000); assert_eq!(loader.sections[1].image_offset, 0x1000);
assert!(loader.sections[1].does_flag_contains_key(crate::simulator::loader::FlagValue::ShfAlloc)); assert!(loader.sections[1].does_flag_contains_key(crate::simulator::loader::FlagValue::ShfAlloc));
assert_eq!(loader.sections[2].virt_addr, 0x400_000); assert_eq!(loader.sections[2].virt_addr, 0x0040_0000);
assert_eq!(loader.sections[2].image_offset, 0x2000); assert_eq!(loader.sections[2].image_offset, 0x2000);
assert!(loader.sections[2].does_flag_contains_key(crate::simulator::loader::FlagValue::ShfAlloc)); assert!(loader.sections[2].does_flag_contains_key(crate::simulator::loader::FlagValue::ShfAlloc));
} }

View File

@ -228,7 +228,7 @@ impl Machine {
s s
} }
pub fn raise_exception(&mut self, exception: ExceptionType, address : u64, system: &mut System) -> Result<MachineOk, MachineError>{ pub fn raise_exception(&mut self, exception: ExceptionType, _address : u64, system: &mut System) -> Result<MachineOk, MachineError>{
self.set_status(MachineStatus::SystemMode); self.set_status(MachineStatus::SystemMode);
// Handle the interruption // Handle the interruption
match exception::call(&exception, self, system) { match exception::call(&exception, self, system) {

View File

@ -1,31 +1,14 @@
//! # Memory Comparator ///! FILE.TXT FORMAT Representing machine memory memory
//! /// - PC
//! This module contains a MemChecker. /// - SP
//! /// - Section_1
//! It's used to compare state memory obtained after a dump memory from NachOS and BurritOS. /// - Section_2
//! /// - ...
//! This module is used exclusively for testing the instruction simulator. /// - Section_n
//! ///
//! Basic usage: /// Each section is divided in 3 parts, on two lines of text
//! /// addr SPACE len
//! ``` /// content
//! 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 std::{fs, io::{BufRead, BufReader, Lines, Error}};
use crate::Machine; use crate::Machine;
@ -111,7 +94,7 @@ impl MemChecker{
/// Extract the values of pc, sp and sections /// Extract the values of pc, sp and sections
/// ///
/// ### Parameter /// ### Parameter
/// - **path** addr to the file /// -**path** addr to the file
/// ///
/// ### Return /// ### Return
/// Mem-checker filled /// Mem-checker filled

View File

@ -1,38 +1,18 @@
//! # MMU
//!
//! This module contains a MMU implementation
//!
//! This part isn't tested nor integrated to BurritOS because of the lack of pagination implementation
//!
//!
use crate::simulator::translationtable::*; use crate::simulator::translationtable::*;
use crate::simulator::machine::*; 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>{ pub struct MMU <'a>{
/// Reference to a page table /* 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
*/
translationTable : Option<&'a mut TranslationTable>, translationTable : Option<&'a mut TranslationTable>,
/// The number of physique pages
numPhyPages : u64, numPhyPages : u64,
/// Size of each page
pageSize : u64 pageSize : u64
} }
impl <'a>MMU <'_>{ 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>{ fn create(numPhyPages: u64, pageSize: u64) -> MMU <'a>{
MMU { MMU {
translationTable : None, translationTable : None,

View File

@ -1,12 +1,3 @@
//! 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 machine;
pub mod error; pub mod error;
pub mod instruction; pub mod instruction;

View File

@ -21,7 +21,7 @@ impl RegisterNum for i64 {}
impl RegisterNum for f32 {} impl RegisterNum for f32 {}
/// Machine register array /// Machine register array
#[derive(PartialEq)] #[derive(PartialEq, Eq)]
pub struct Register<U: RegisterNum> { pub struct Register<U: RegisterNum> {
/// 32 available registers of type U /// 32 available registers of type U
register: [U; 32] register: [U; 32]

View File

@ -1,40 +1,28 @@
//! # Translation Table //Nombre maximum de correspondances dans une table des pages
//! //Cette donnée devra a terme etre recupérée depuis un fichier de configuration
//! 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; const MaxVirtPages : u64 = 200000;
/// Translation Table corresponding to a process
/// An iteration of type TranslationTable should be possesses by an oject of type Process /* Une table de correspondance propre à un processus
* Une variable de type TranslationTable devra etre possédée par un objet de type Process
*/
pub struct TranslationTable{ pub struct TranslationTable{
/// Table size <=> nb of possible translation //capacité de cette table <=> nombre de correspondances possibles
//A voir si cette donnée doit etre immuable
pub maxNumPages : u64, pub maxNumPages : u64,
///The table *Vec impemente Index Trait* //la table en question
//Vec implemente le trait Index, donc un bon choix
pub pageTable : Vec<PageTableEntry> pub pageTable : Vec<PageTableEntry>
} }
impl TranslationTable { impl TranslationTable {
/// TranslationTable constructor
///
/// ### Return
/// TranslationTable with an empty Vector
pub fn create() -> TranslationTable { pub fn create() -> TranslationTable {
let mut tmp_vec : Vec<PageTableEntry> = Vec::new(); let mut tmp_vec : Vec<PageTableEntry> = Vec::new();
for i in 0..MaxVirtPages { for _i in 0..MaxVirtPages {
tmp_vec.push(PageTableEntry::create()); tmp_vec.push(PageTableEntry::create());
} }
@ -48,7 +36,7 @@ impl TranslationTable {
//Assert a mettre dans chacune des fonctions suivantes //Assert a mettre dans chacune des fonctions suivantes
pub fn get_max_num_pages(&self) -> u64{ pub fn get_max_num_pages(&self) -> u64{
return self.maxNumPages; self.maxNumPages
} }
pub fn set_physical_page(&mut self, vpn : u64, physical_page : i32){ pub fn set_physical_page(&mut self, vpn : u64, physical_page : i32){

View File

@ -9,7 +9,7 @@ use std::ptr;
/// These methods wrap unsafe instructions because it doesn't respect borrow rules per example /// 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.) /// but everything has been tested with miri to assure there's no Undefined Behaviour (use-after-free, double free, etc.)
/// or memory leak /// or memory leak
#[derive(PartialEq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug)]
pub struct List<T: PartialEq> { pub struct List<T: PartialEq> {
head: Link<T>, head: Link<T>,
tail: Link<T>, tail: Link<T>,