diff --git a/Cargo.lock b/Cargo.lock index 5b90585..9898199 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,7 @@ name = "burritos" version = "0.1.0" dependencies = [ "lazy_static", + "libc", ] [[package]] @@ -14,3 +15,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" diff --git a/Cargo.toml b/Cargo.toml index fe2c644..d9e3b00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,4 @@ edition = "2021" [dependencies] lazy_static = "1.4.0" +libc = { version = "0.2.139", features = ["extra_traits"] } diff --git a/src/kernel/mod.rs b/src/kernel/mod.rs index bbd9f52..e061a2a 100644 --- a/src/kernel/mod.rs +++ b/src/kernel/mod.rs @@ -2,4 +2,5 @@ mod process; pub mod thread; pub mod scheduler; pub mod mgerror; -pub mod system; \ No newline at end of file +pub mod system; +mod ucontext; \ No newline at end of file diff --git a/src/kernel/thread.rs b/src/kernel/thread.rs index 12d9db4..000877a 100644 --- a/src/kernel/thread.rs +++ b/src/kernel/thread.rs @@ -1,14 +1,10 @@ -use std::sync::Arc; +use std::{sync::Arc}; -use super::{process::Process, mgerror::ErrorCode, system::{ObjectType, G_ALIVE, G_SCHEDULER}}; +use super::{process::Process, mgerror::ErrorCode, system::{ObjectType, G_ALIVE, G_SCHEDULER}, ucontext::UContextT}; use crate::{simulator::machine::{NUM_INT_REGS, NUM_FP_REGS, STACK_REG}}; const SIMULATORSTACKSIZE: usize = 32 * 1024; - -#[derive(PartialEq)] -struct SimulatorContext { - // todo -} +const STACK_FENCEPOST: u32 = 0xdeadbeef; #[derive(PartialEq)] struct ThreadContext { @@ -21,7 +17,7 @@ struct ThreadContext { pub struct Thread { name: String, process: Option, - simulation_context: SimulatorContext, + // simulation_context: UContextT, thread_context: ThreadContext, stack_pointer: i32, object_type: ObjectType @@ -33,7 +29,7 @@ impl Thread { Self { name, process: None, - simulation_context: SimulatorContext { }, + // simulation_context: UContextT::new(), thread_context: ThreadContext { int_registers: [0; NUM_INT_REGS], float_registers: [0; NUM_FP_REGS], @@ -79,7 +75,18 @@ impl Thread { } fn init_simulator_context(&self, base_stack_addr: [i8; SIMULATORSTACKSIZE]) { - todo!(); + // let res = self.simulation_context.get_context(); + // if res != 0 { + // panic!("getcontext returns non-zero value {}", res); + // } + // self.simulation_context.buf.uc_stack.ss_sp = base_stack_addr; + // self.simulation_context.buf.uc_stack.ss_size = base_stack_addr.len(); + // self.simulation_context.buf.uc_stack.ss_flags = 0; + // self.simulation_context.buf.uc_link = UContextT::new().buf; + // self.simulation_context.make_context(start_thread_execution, 0); + + // self.simulation_context.stackBottom = base_stack_addr.to_vec(); + // self.simulation_context.stackBottom[0] = STACK_FENCEPOST; } /// Wait for another thread to finish its execution @@ -147,4 +154,8 @@ impl Drop for Thread { todo!(); } +} + +fn start_thread_execution() { + } \ No newline at end of file diff --git a/src/kernel/ucontext.rs b/src/kernel/ucontext.rs new file mode 100644 index 0000000..89b847d --- /dev/null +++ b/src/kernel/ucontext.rs @@ -0,0 +1,72 @@ + +use std::mem::MaybeUninit; + +use libc::{ucontext_t, getcontext, setcontext, makecontext}; + +/// Safe wrapper for ucontext_t struct of linux-gnu libc +/// +/// setcontext and getcontext are unsafe function, this wrap unsafe libc functions +/// +/// This struct doesn't work on windows, because this struct is unavailable +/// +/// todo ucontext_t is not thread-safe (doesn't implements Send and Sync trait), and cannot be use in Threads as rust require var in Mutex (see system.rs) to have everything inside to implements thread-safe traits +#[derive(PartialEq)] +pub struct UContextT { + #[cfg(not(target_os = "windows"))] // struct non disponible sur la libc sur windows + pub buf: ucontext_t, + pub stackBottom: Vec +} + +#[cfg(not(target_os = "windows"))] +impl UContextT { + + pub fn new() -> Self { + let mut context = MaybeUninit::::uninit(); + unsafe { getcontext(context.as_mut_ptr()) }; + Self { + buf: unsafe { context.assume_init() }, + stackBottom: Vec::default(), + } + } + + /// Get user context and store it in variable pointed to by UCP. + /// + /// Use `man getcontext` for more informations + pub fn get_context(&mut self) -> i32 { + unsafe { + getcontext(&mut self.buf) + } + } + + /// Set user context from information of variable pointed to by UCP. + /// + /// Use `man setcontext` for more informations + pub fn set_context(&mut self) -> i32 { + unsafe { + setcontext(&self.buf) + } + } + + pub fn make_context(&mut self, func: extern "C" fn(), args: i32) { + unsafe { + makecontext(&mut self.buf, func, args) + } + } + +} + +#[cfg(target_os = "windows")] +impl UContextT { + + pub fn new() -> Self { + Self {} + } + + pub fn get_context(&mut self) { + // no op + } + + pub fn set_context(&mut self) { + // no op + } +} \ No newline at end of file