use crate::{MemoryAddress, MemoryRange, PID, TID}; use core::convert::TryInto; mod mem; pub use mem::*; #[derive(Debug, Clone, Copy, PartialEq)] pub struct ProcessArgs { name: [u8; 16], } #[derive(Debug, Clone, Copy, PartialEq)] pub struct ThreadInit { pub call: fn(data: usize) -> usize, pub stack: MemoryRange, pub arg: Option, pub name: [u8; 12], } impl ThreadInit { pub fn new( call: fn(data: usize) -> usize, stack: MemoryRange, arg: Option, name: [u8; 12], ) -> Self { ThreadInit { call, stack, arg, name, } } } impl Default for ThreadInit { fn default() -> Self { ThreadInit { call: unsafe { core::mem::transmute:: usize>(4) }, stack: MemoryRange::new(4, 4).unwrap(), arg: None, name: [0; 12], } } } #[derive(Copy, Clone, Debug, PartialEq)] pub struct ProcessKey([u8; 8]); impl ProcessKey { pub fn new(key: [u8; 8]) -> ProcessKey { ProcessKey(key) } } #[derive(Copy, Clone, Debug, PartialEq)] pub struct ProcessInit { pub key: ProcessKey, } pub struct WaitHandle(core::marker::PhantomData); pub struct ProcessHandle(()); pub fn thread_to_args(call: usize, init: &ThreadInit) -> [usize; 8] { [ call as usize, init.call as usize, init.stack.as_ptr() as _, init.stack.len(), init.arg.map(|x| x.get()).unwrap_or_default(), 0, 0, 0, ] } /// This code is executed inside the kernel. It takes the list of args /// that were passed via registers and converts them into a `ThreadInit` /// struct with enough information to start the new thread. pub fn args_to_thread( a1: usize, a2: usize, a3: usize, a4: usize, _a5: usize, _a6: usize, _a7: usize, ) -> core::result::Result { let call = unsafe { core::mem::transmute(a1) }; let stack = MemoryRange::new(a2, a3).map_err(|_| crate::Error::InvalidSyscall)?; let arg = MemoryAddress::new(a4); Ok(ThreadInit { call, stack, arg, name: [0; 12], }) } pub fn create_thread_pre(_f: &F) -> core::result::Result where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static, { todo!() // Ok(ThreadInit {}) } pub fn create_thread_post( _f: F, _thread_id: TID, ) -> core::result::Result, crate::Error> where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static, { todo!() // let server_address = xous_address(); // let server_connection = // XOUS_SERVER_CONNECTION.with(|xsc| xsc.borrow().as_ref().unwrap().clone()); // let process_id = PROCESS_ID.with(|pid| *pid.borrow()); // Ok(std::thread::Builder::new() // .spawn(move || { // set_xous_address(server_address); // THREAD_ID.with(|tid| *tid.borrow_mut() = thread_id); // PROCESS_ID.with(|pid| *pid.borrow_mut() = process_id); // XOUS_SERVER_CONNECTION.with(|xsc| *xsc.borrow_mut() = Some(server_connection)); // f() // }) // .map(WaitHandle) // .map_err(|_| crate::Error::InternalError)?) } pub fn wait_thread(_joiner: WaitHandle) -> crate::SysCallResult { todo!() // joiner // .0 // .join() // .map(|_| Result::Ok) // .map_err(|_| crate::Error::InternalError) } pub fn process_to_args(call: usize, init: &ProcessInit) -> [usize; 8] { [ call, u32::from_le_bytes(init.key.0[0..4].try_into().unwrap()) as _, u32::from_le_bytes(init.key.0[4..8].try_into().unwrap()) as _, u32::from_le_bytes(init.key.0[8..12].try_into().unwrap()) as _, u32::from_le_bytes(init.key.0[12..16].try_into().unwrap()) as _, 0, 0, 0, ] } pub fn args_to_process( _a1: usize, _a2: usize, _a3: usize, _a4: usize, _a5: usize, _a6: usize, _a7: usize, ) -> core::result::Result { todo!() } pub fn create_thread_simple_pre( f: &fn(T) -> U, arg: &T, ) -> core::result::Result where T: Send + 'static, U: Send + 'static, { let stack = crate::map_memory( None, None, 131_072, crate::MemoryFlags::R | crate::MemoryFlags::W | crate::MemoryFlags::RESERVE, )?; let start = unsafe { core::mem::transmute(*f) }; let arg = unsafe { core::mem::transmute(arg) }; Ok(ThreadInit::new(start, stack, Some(arg), [0; 12])) } pub fn create_thread_simple_post( _f: fn(T) -> U, _arg: T, _thread_id: TID, ) -> core::result::Result, crate::Error> where T: Send + 'static, U: Send + 'static, { Ok(WaitHandle(core::marker::PhantomData)) } /// If no connection exists, create a new connection to the server. This means /// our parent PID will be PID1. Otherwise, reuse the same connection. pub fn create_process_pre(_args: &ProcessArgs) -> core::result::Result { todo!() } pub fn create_process_post( _args: ProcessArgs, _init: ProcessInit, _pid: PID, ) -> core::result::Result { todo!() } pub fn wait_process(_joiner: ProcessHandle) -> crate::SysCallResult { loop { crate::wait_event(); } }