xous-ipc-test/xous-rs/src/arch/native.rs

219 lines
5.4 KiB
Rust

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<MemoryAddress>,
pub name: [u8; 12],
}
impl ThreadInit {
pub fn new(
call: fn(data: usize) -> usize,
stack: MemoryRange,
arg: Option<MemoryAddress>,
name: [u8; 12],
) -> Self {
ThreadInit {
call,
stack,
arg,
name,
}
}
}
impl Default for ThreadInit {
fn default() -> Self {
ThreadInit {
call: unsafe { core::mem::transmute::<usize, fn(data: usize) -> 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<T>(core::marker::PhantomData<T>);
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<ThreadInit, crate::Error> {
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, T>(_f: &F) -> core::result::Result<ThreadInit, crate::Error>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
{
todo!()
// Ok(ThreadInit {})
}
pub fn create_thread_post<F, T>(
_f: F,
_thread_id: TID,
) -> core::result::Result<WaitHandle<T>, 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<T>(_joiner: WaitHandle<T>) -> 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<ProcessInit, crate::Error> {
todo!()
}
pub fn create_thread_simple_pre<T, U>(
f: &fn(T) -> U,
arg: &T,
) -> core::result::Result<ThreadInit, crate::Error>
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<T, U>(
_f: fn(T) -> U,
_arg: T,
_thread_id: TID,
) -> core::result::Result<WaitHandle<U>, 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<ProcessInit, crate::Error> {
todo!()
}
pub fn create_process_post(
_args: ProcessArgs,
_init: ProcessInit,
_pid: PID,
) -> core::result::Result<ProcessHandle, crate::Error> {
todo!()
}
pub fn wait_process(_joiner: ProcessHandle) -> crate::SysCallResult {
loop {
crate::wait_event();
}
}