merge branch documentation
This commit is contained in:
commit
638f96336b
12
build.rs
Normal file
12
build.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//! 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());
|
||||||
|
}
|
@ -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 std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}}};
|
use crate::{simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}}};
|
||||||
@ -292,6 +297,7 @@ fn sc_new_thread(machine: &mut Machine, system: &mut System) -> Result<MachineOk
|
|||||||
} else {
|
} else {
|
||||||
return Err("Process owner of current thread is none")?;
|
return Err("Process owner of current thread is none")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sc_join(machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
|
fn sc_join(machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
//! # 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 {
|
||||||
|
@ -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 process;
|
||||||
pub mod thread;
|
pub mod thread;
|
||||||
pub mod mgerror;
|
pub mod mgerror;
|
||||||
|
@ -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::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;
|
||||||
@ -6,13 +14,14 @@ 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 simultanous Semaphore
|
/// Counter of simultaneous Semaphore
|
||||||
pub counter:i32,
|
pub counter:i32,
|
||||||
/// QUeue of Semaphore waiting to be exucated
|
/// QUeue of Semaphore waiting to be executed
|
||||||
pub waiting_queue:List<Rc<RefCell<Thread>>>,
|
pub waiting_queue:List<Rc<RefCell<Thread>>>,
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -49,7 +58,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 initialy free
|
/// The lock is initially free
|
||||||
///
|
///
|
||||||
/// ### Parameters
|
/// ### Parameters
|
||||||
/// - **thread_manager** Thread manager which managing threads
|
/// - **thread_manager** Thread manager which managing threads
|
||||||
@ -72,7 +81,7 @@ 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 = Option::Some(match thread_manager.get_g_current_thread() {
|
self.owner = Some(match thread_manager.get_g_current_thread() {
|
||||||
Some(th) => {
|
Some(th) => {
|
||||||
Rc::clone(&th)
|
Rc::clone(&th)
|
||||||
},
|
},
|
||||||
@ -128,8 +137,14 @@ impl Lock {
|
|||||||
machine.interrupt.set_status(old_status);
|
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.
|
/// 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) =>
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
//! # 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};
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
#![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(missing_docs)]
|
||||||
#![warn(clippy::missing_docs_in_private_items)]
|
#![warn(clippy::missing_docs_in_private_items)]
|
||||||
|
|
||||||
@ -7,10 +10,8 @@
|
|||||||
//! Burritos is an educational operating system written in Rust
|
//! Burritos is an educational operating system written in Rust
|
||||||
//! running on RISC-V emulator.
|
//! running on RISC-V emulator.
|
||||||
|
|
||||||
/// Contain hardware simulated part of the machine
|
|
||||||
mod simulator;
|
mod simulator;
|
||||||
mod kernel;
|
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;
|
pub mod utility;
|
||||||
|
|
||||||
use std::{rc::Rc, cell::RefCell};
|
use std::{rc::Rc, cell::RefCell};
|
||||||
@ -59,7 +60,6 @@ fn main() {
|
|||||||
system.get_thread_manager().set_sp_max(sp_max);
|
system.get_thread_manager().set_sp_max(sp_max);
|
||||||
system.get_thread_manager().start_thread(Rc::clone(&thread_exec), owner1, loader.elf_header.entrypoint, sp_max, -1);
|
system.get_thread_manager().start_thread(Rc::clone(&thread_exec), owner1, loader.elf_header.entrypoint, sp_max, -1);
|
||||||
|
|
||||||
|
|
||||||
let to_run = system.get_thread_manager().find_next_to_run().unwrap();
|
let to_run = system.get_thread_manager().find_next_to_run().unwrap();
|
||||||
system.get_thread_manager().switch_to(&mut machine, Rc::clone(&to_run));
|
system.get_thread_manager().switch_to(&mut machine, Rc::clone(&to_run));
|
||||||
|
|
||||||
|
@ -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)]
|
#[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;
|
||||||
@ -25,6 +46,7 @@ impl Interrupt {
|
|||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Interupt getter
|
||||||
pub fn get_status(&self) -> InterruptStatus {
|
pub fn get_status(&self) -> InterruptStatus {
|
||||||
self.level
|
self.level
|
||||||
}
|
}
|
||||||
|
@ -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 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 <https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header> for more informations
|
/// see [ELF file Header](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
|
||||||
|
@ -1,14 +1,31 @@
|
|||||||
///! FILE.TXT FORMAT Representing machine memory memory
|
//! # Memory Comparator
|
||||||
/// - PC
|
//!
|
||||||
/// - SP
|
//! This module contains a MemChecker.
|
||||||
/// - Section_1
|
//!
|
||||||
/// - Section_2
|
//! It's used to compare state memory obtained after a dump memory from NachOS and BurritOS.
|
||||||
/// - ...
|
//!
|
||||||
/// - Section_n
|
//! This module is used exclusively for testing the instruction simulator.
|
||||||
///
|
//!
|
||||||
/// Each section is divided in 3 parts, on two lines of text
|
//! Basic usage:
|
||||||
/// 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;
|
||||||
|
@ -1,18 +1,38 @@
|
|||||||
|
//! # 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>{
|
||||||
/* Un MMU possède une seule référence vers une table des pages à un instant donné
|
/// Reference to a page table
|
||||||
* 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,
|
||||||
|
@ -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 machine;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod instruction;
|
pub mod instruction;
|
||||||
|
@ -1,23 +1,35 @@
|
|||||||
//Nombre maximum de correspondances dans une table des pages
|
//! # Translation Table
|
||||||
//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
|
||||||
/* Une table de correspondance propre à un processus
|
/// An iteration of type TranslationTable should be possesses by an oject of type Process
|
||||||
* Une variable de type TranslationTable devra etre possédée par un objet de type Process
|
|
||||||
*/
|
|
||||||
pub struct TranslationTable{
|
pub struct TranslationTable{
|
||||||
//capacité de cette table <=> nombre de correspondances possibles
|
/// Table size <=> nb of possible translation
|
||||||
//A voir si cette donnée doit etre immuable
|
|
||||||
pub maxNumPages : u64,
|
pub maxNumPages : u64,
|
||||||
|
|
||||||
//la table en question
|
///The table *Vec impemente Index Trait*
|
||||||
//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();
|
||||||
|
@ -104,6 +104,10 @@ pub fn get_debug_configuration() -> Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Removes comments and empty lines
|
/// Removes comments and empty lines
|
||||||
|
/// Filters out empty lines and comments from the reader `BufReader`.
|
||||||
|
///
|
||||||
|
/// Returns a [`Vec<String>`], each entry containing a valid
|
||||||
|
/// line from the input file.
|
||||||
fn filter_garbage<R: std::io::Read>(reader: BufReader<R>) -> Vec<String> {
|
fn filter_garbage<R: std::io::Read>(reader: BufReader<R>) -> Vec<String> {
|
||||||
reader.lines()
|
reader.lines()
|
||||||
.map(|l| l.unwrap())
|
.map(|l| l.unwrap())
|
||||||
@ -111,11 +115,13 @@ fn filter_garbage<R: std::io::Read>(reader: BufReader<R>) -> Vec<String> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Inserts user settings into setting map
|
/// Inserts user settings into setting map
|
||||||
|
/// Adds a <K, V> pair to a [`Settings`] map.
|
||||||
|
///
|
||||||
|
/// Returns the updated [`Settings`].
|
||||||
fn update_settings_map(mut settings_map: Settings, key: &str, setting: &str) -> Settings {
|
fn update_settings_map(mut settings_map: Settings, key: &str, setting: &str) -> Settings {
|
||||||
let key = MachineSettingKey::from(key);
|
let key = MachineSettingKey::from(key);
|
||||||
let setting = setting.parse::<u64>().unwrap_or(0);
|
let setting = str::parse::<u64>(setting).unwrap_or(0);
|
||||||
settings_map.insert(key, setting);
|
settings_map.insert(key, setting);
|
||||||
settings_map
|
settings_map
|
||||||
}
|
}
|
@ -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 list;
|
||||||
pub mod objaddr;
|
pub mod objaddr;
|
||||||
pub mod cfg;
|
pub mod cfg;
|
@ -17,9 +17,13 @@ use crate::kernel::{synch::{ Semaphore, Lock }, thread::Thread};
|
|||||||
/// calls.
|
/// calls.
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub struct ObjAddr {
|
pub struct ObjAddr {
|
||||||
|
/// Id of the last added object
|
||||||
last_id: i32,
|
last_id: i32,
|
||||||
|
/// List of [Semaphore] added in this struct. Each is keyed with a unique i32 id.
|
||||||
semaphores: HashMap<i32, Semaphore>,
|
semaphores: HashMap<i32, Semaphore>,
|
||||||
|
/// List of [Lock] added in this struct. Each is keyed with a unique i32 id.
|
||||||
locks: HashMap<i32, Lock>,
|
locks: HashMap<i32, Lock>,
|
||||||
|
/// List of threads known by this instance of ObjAddr (useful for managing lock ownership)
|
||||||
threads: HashMap<i32, Rc<RefCell<Thread>>>,
|
threads: HashMap<i32, Rc<RefCell<Thread>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user