From 30c66a1cdda0110c020b865e271a5e41373b46f3 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sat, 6 Jan 2024 00:13:59 +0800 Subject: [PATCH] about to add argument support Signed-off-by: Sean Cross --- crates/riscv-cpu/src/mmu.rs | 23 +++- src/xous.rs | 35 ++---- src/xous/services.rs | 90 +++++++++++--- src/xous/services/log.rs | 120 ++++++++++++++++-- src/xous/services/name.rs | 179 +++++++++++++++++++++++++++ src/xous/services/panic_to_screen.rs | 39 ++++++ src/xous/services/ticktimer.rs | 34 ++++- src/xous/syscalls.rs | 87 +++++++++---- 8 files changed, 519 insertions(+), 88 deletions(-) create mode 100644 src/xous/services/name.rs create mode 100644 src/xous/services/panic_to_screen.rs diff --git a/crates/riscv-cpu/src/mmu.rs b/crates/riscv-cpu/src/mmu.rs index 724dd7a..348fd1e 100644 --- a/crates/riscv-cpu/src/mmu.rs +++ b/crates/riscv-cpu/src/mmu.rs @@ -1,4 +1,5 @@ use std::{ + collections::HashMap, sync::mpsc::Receiver, sync::{Arc, Mutex}, }; @@ -51,11 +52,12 @@ pub struct Mmu { privilege_mode: PrivilegeMode, memory: Arc>, - // /// The size of main memory (if initialized) - // memory_length: Option, /// Address translation can be affected `mstatus` (MPRV, MPP in machine mode) /// then `Mmu` has copy of it. mstatus: u64, + + /// A cache of instructions. We assume that instruction memory does not change. + instruction_cache: Arc>>, } #[derive(Debug)] @@ -96,6 +98,7 @@ impl Mmu { privilege_mode: PrivilegeMode::Machine, memory, mstatus: 0, + instruction_cache: Arc::new(Mutex::new(HashMap::new())), } } @@ -170,13 +173,23 @@ impl Mmu { /// # Arguments /// * `v_address` Virtual address pub fn fetch_word(&self, v_address: u64) -> Result { + // if let Some(data) = self.instruction_cache.lock().unwrap().get(&v_address) { + // return Ok(*data); + // } let width = 4; if (v_address & 0xfff) <= (0x1000 - width) { // Fast path. All bytes fetched are in the same page so // translating an address only once. let effective_address = self.trim_to_xlen(v_address); self.translate_address(effective_address, &MemoryAccessType::Execute) - .map(|p_address| self.load_word_raw(p_address)) + .map(|p_address| { + let data = self.load_word_raw(p_address); + self.instruction_cache + .lock() + .unwrap() + .insert(v_address, data); + data + }) .map_err(|()| Trap { trap_type: TrapType::InstructionPageFault, value: effective_address, @@ -189,6 +202,10 @@ impl Mmu { Err(e) => return Err(e), }; } + self.instruction_cache + .lock() + .unwrap() + .insert(v_address, data); Ok(data) } } diff --git a/src/xous.rs b/src/xous.rs index 1d92735..07e06db 100644 --- a/src/xous.rs +++ b/src/xous.rs @@ -147,7 +147,6 @@ struct Memory { free_pages: BTreeSet, heap_start: u32, heap_size: u32, - // allocation_start: u32, allocation_previous: u32, l1_pt: u32, satp: u32, @@ -664,33 +663,13 @@ impl riscv_cpu::cpu::Memory for Memory { argument_2, argument_3, argument_4, - ) => { - let (tx, rx) = std::sync::mpsc::channel(); - self.memory_cmd - .send(MemoryCommand::CreateThread( - entry_point as _, - stack_pointer as _, - stack_length as _, - argument_1 as _, - argument_2 as _, - argument_3 as _, - argument_4 as _, - tx, - )) - .unwrap(); - let thread_id = rx.recv().unwrap(); - [ - SyscallResultNumber::ThreadId as i64, - thread_id, - 0, - 0, - 0, - 0, - 0, - 0, - ] - .into() - } + ) => syscalls::create_thread( + self, + entry_point, + stack_pointer, + stack_length, + [argument_1, argument_2, argument_3, argument_4], + ), Syscall::UnmapMemory(address, size) => { // println!("UnmapMemory({:08x}, {})", address, size); for offset in (address..address + size).step_by(4096) { diff --git a/src/xous/services.rs b/src/xous/services.rs index 0c744a6..bea4e2a 100644 --- a/src/xous/services.rs +++ b/src/xous/services.rs @@ -1,6 +1,9 @@ use std::sync::mpsc::Receiver; pub mod log; +pub mod name; +pub mod panic_to_screen; pub mod ticktimer; +use super::Memory; pub type ResponseData = ([i64; 8], Option<(Vec, u64)>); @@ -19,48 +22,97 @@ pub enum LendResult { } pub trait Service { - fn scalar(&mut self, sender: u32, opcode: u32, _args: [u32; 4]) { - panic!("Unknown scalar to service {}: {}", sender, opcode); - } - fn blocking_scalar(&mut self, sender: u32, opcode: u32, _args: [u32; 4]) -> ScalarResult { - panic!("Unknown scalar to service {}: {}", sender, opcode); - } - fn lend(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) -> LendResult { + fn scalar(&mut self, _memory: &mut Memory, sender: u32, opcode: u32, args: [u32; 4]) { panic!( - "Unknown lend to service {}: {} ({:?})", - sender, opcode, extra + "Unknown scalar to service {}: {} ({:?})", + sender, opcode, args ); } - /// Mutable lend messages may block - fn lend_mut( + fn blocking_scalar( &mut self, + _memory: &mut Memory, sender: u32, opcode: u32, - _buf: &mut [u8], + args: [u32; 4], + ) -> ScalarResult { + panic!( + "Unknown scalar to service {}: {} ({:?})", + sender, opcode, args + ); + } + + fn lend( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + buf: &[u8], extra: [u32; 2], ) -> LendResult { panic!( - "Unknown lend_mut to service {}: {} ({:?})", - sender, opcode, extra + "Unknown lend {} bytes to service {}: {} ({:?})", + buf.len(), + sender, + opcode, + extra ); } - /// Send-type messages return immediately, and memory is detached from the host process. - fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) { + fn lend_mut( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + buf: &mut [u8], + extra: [u32; 2], + ) -> LendResult { panic!( - "Unknown send to service {}: {} ({:?})", - sender, opcode, extra + "Unknown lend_mut {} bytes to service {}: {} ({:?})", + buf.len(), + sender, + opcode, + extra + ); + } + + fn send( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + buf: &[u8], + extra: [u32; 2], + ) { + panic!( + "Unknown send {} bytes to service {}: {} ({:?})", + buf.len(), + sender, + opcode, + extra ); } } pub fn get_service(name: &[u32; 4]) -> Option> { + let mut output_bfr = [0u8; core::mem::size_of::() * 4 /*args.len()*/]; + // Combine the four arguments to form a single + // contiguous buffer. Note: The buffer size will change + // depending on the platfor's `usize` length. + for (src, dest) in name.iter().zip(output_bfr.chunks_mut(4)) { + dest.copy_from_slice(src.to_le_bytes().as_ref()); + } + println!( + "Connecting to service: {}", + std::str::from_utf8(&output_bfr).unwrap_or("") + ); + match name { [0x6b636974, 0x656d6974, 0x65732d72, 0x72657672] => { Some(Box::new(ticktimer::Ticktimer::new())) } [0x73756f78, 0x676f6c2d, 0x7265732d, 0x20726576] => Some(Box::new(log::Log::new())), - _ => None, + [0x73756f78, 0x6d616e2d, 0x65732d65, 0x72657672] => Some(Box::new(name::Name::new())), + _ => panic!("Unhandled service request: {:x?}", name), } } diff --git a/src/xous/services/log.rs b/src/xous/services/log.rs index d648726..623049a 100644 --- a/src/xous/services/log.rs +++ b/src/xous/services/log.rs @@ -1,4 +1,5 @@ use super::{LendResult, ScalarResult, Service}; +use crate::xous::Memory; use std::io::Write; enum LogLendOpcode { @@ -9,11 +10,54 @@ enum LogLendOpcode { StandardError = 2, } +#[allow(dead_code)] +enum LogSendOpcode { + /// A panic occurred, and a panic log is forthcoming + PanicStarted = 1000, + + /// Log messages of varying size + PanicMessage0 = 1100, + PanicMessage1 = 1101, + PanicMessage2 = 1102, + PanicMessage3 = 1103, + PanicMessage4 = 1104, + PanicMessage5 = 1105, + PanicMessage6 = 1106, + PanicMessage7 = 1107, + PanicMessage8 = 1108, + PanicMessage9 = 1109, + PanicMessage10 = 1110, + PanicMessage11 = 1111, + PanicMessage12 = 1112, + PanicMessage13 = 1113, + PanicMessage14 = 1114, + PanicMessage15 = 1115, + PanicMessage16 = 1116, + PanicMessage17 = 1117, + PanicMessage18 = 1118, + PanicMessage19 = 1119, + PanicMessage20 = 1120, + PanicMessage21 = 1121, + PanicMessage22 = 1122, + PanicMessage23 = 1123, + PanicMessage24 = 1124, + PanicMessage25 = 1125, + PanicMessage26 = 1126, + PanicMessage27 = 1127, + PanicMessage28 = 1128, + PanicMessage29 = 1129, + PanicMessage30 = 1130, + PanicMessage31 = 1131, + PanicMessage32 = 1132, + + /// End of a panic + PanicFinished = 1200, +} + pub struct Log {} impl Log { pub fn new() -> Self { - // println!("Constructing a log server"); Log {} } } @@ -25,16 +69,64 @@ impl Default for Log { } impl Service for Log { - fn scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) { - println!("Log scalar {}: {} {:x?}", sender, opcode, args); + fn scalar(&mut self, _memory: &mut Memory, sender: u32, opcode: u32, args: [u32; 4]) { + let message_bytes = if opcode >= LogSendOpcode::PanicMessage0 as u32 + && opcode <= LogSendOpcode::PanicMessage32 as u32 + { + Some(opcode - LogSendOpcode::PanicMessage0 as u32) + } else { + None + }; + + if LogSendOpcode::PanicStarted as u32 == opcode { + println!("Panic started"); + } else if LogSendOpcode::PanicFinished as u32 == opcode { + println!(); + println!("Panic finished"); + } else if let Some(message_bytes) = message_bytes { + let mut output_bfr = [0u8; core::mem::size_of::() * 4 /*args.len()*/]; + // let mut output_iter = output_bfr.iter_mut(); + + // Combine the four arguments to form a single + // contiguous buffer. Note: The buffer size will change + // depending on the platfor's `usize` length. + for (src, dest) in args.iter().zip(output_bfr.chunks_mut(4)) { + dest.copy_from_slice(src.to_le_bytes().as_ref()); + // for src in word.to_le_bytes().iter() { + // *(output_iter.next().unwrap()) = *src; + // } + } + print!( + "{}", + std::str::from_utf8(&output_bfr[0..message_bytes as usize]).unwrap_or("") + ); + } else { + println!("Log scalar {}: {} {:x?}", sender, opcode, args); + } } - fn blocking_scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) -> ScalarResult { - println!("Log blocking_scalar {}: {} {:x?}", sender, opcode, args); + fn blocking_scalar( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + args: [u32; 4], + ) -> ScalarResult { + println!( + "Unhandled log blocking_scalar {}: {} {:x?}", + sender, opcode, args + ); ScalarResult::Scalar1(0) } - fn lend(&mut self, sender: u32, opcode: u32, buf: &[u8], extra: [u32; 2]) -> LendResult { + fn lend( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + buf: &[u8], + extra: [u32; 2], + ) -> LendResult { if opcode == LogLendOpcode::StandardOutput as u32 { let print_buffer = &buf[0..extra[1] as usize]; // println!("Log stdout:"); @@ -46,23 +138,31 @@ impl Service for Log { std::io::stderr().write_all(print_buffer).unwrap(); std::io::stderr().flush().unwrap(); } else { - panic!("Log lend {}: {} {:x?}", sender, opcode, buf); + panic!("Unhandled log lend {}: {} {:x?}", sender, opcode, buf); } LendResult::MemoryReturned([0, 0]) } fn lend_mut( &mut self, + _memory: &mut Memory, sender: u32, opcode: u32, _buf: &mut [u8], extra: [u32; 2], ) -> LendResult { - println!("Log lend_mut {}: {} {:x?}", sender, opcode, extra); + println!("Unhandled log lend_mut {}: {} {:x?}", sender, opcode, extra); LendResult::MemoryReturned([0, 0]) } - fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) { - println!("Log send {}: {} {:x?}", sender, opcode, extra); + fn send( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + _buf: &[u8], + extra: [u32; 2], + ) { + println!("Unhandled log send {}: {} {:x?}", sender, opcode, extra); } } diff --git a/src/xous/services/name.rs b/src/xous/services/name.rs new file mode 100644 index 0000000..5a2bab5 --- /dev/null +++ b/src/xous/services/name.rs @@ -0,0 +1,179 @@ +use crate::xous::Memory; + +use super::{LendResult, ScalarResult, Service}; + +#[allow(dead_code)] +enum NameLendOpcode { + /// Create a new server with the given name and return its SID. + Register = 0, + + /// Create a connection to the target server. + Lookup = 1, + + /// Create an authenticated connection to the target server. + AuthenticatedLookup = 2, + + /// unregister a server, given its cryptographically unique SID. + Unregister = 3, + + /// disconnect, given a server name and a cryptographically unique, one-time use token + Disconnect = 4, + + /// indicates if all inherently trusted slots have been occupied. Should not run untrusted code until this is the case. + TrustedInitDone = 5, + + /// Connect to a Server, blocking if the Server does not exist. When the Server is started, + /// return with either the CID or an AuthenticationRequest + /// + /// # Message Types + /// + /// * MutableLend + /// + /// # Arguments + /// + /// The memory being pointed to should be a &str, and the length of the string should + /// be specified in the `valid` field. + /// + /// # Return Values + /// + /// Memory is overwritten to contain a return value. This return value can be defined + /// as the following enum: + /// + /// ```rust + /// #[repr(C)] + /// #[non_exhaustive] + /// enum ConnectResult { + /// Success(xous::CID /* connection ID */, [u32; 4] /* Disconnection token */), + /// Error(u32 /* error code */), + /// Unhandled, /* Catchall for future Results */ + /// } + /// ``` + BlockingConnect = 6, + + /// Connect to a Server, returning the connection ID or an authentication request if + /// it exists, and returning ServerNotFound if it does not exist. + /// + /// # Message Types + /// + /// * MutableLend + /// + /// # Arguments + /// + /// The memory being pointed to should be a &str, and the length of the string should + /// be specified in the `valid` field. + /// + /// # Return Values + /// + /// Memory is overwritten to contain a return value. This return value can be defined + /// as the following enum: + /// + /// ```rust + /// #[repr(C)] + /// #[non_exhaustive] + /// enum ConnectResult { + /// Success(xous::CID /* connection ID */, [u32; 4] /* Disconnection token */), + /// Error(u32 /* error code */), + /// Unhandled, /* Catchall for future Results */ + /// } + /// ``` + TryConnect = 7, +} + +pub struct Name {} + +impl Name { + pub fn new() -> Self { + Name {} + } +} + +impl Default for Name { + fn default() -> Self { + Self::new() + } +} + +impl Service for Name { + fn scalar(&mut self, _memory: &mut Memory, sender: u32, opcode: u32, args: [u32; 4]) { + panic!("Unhandled name scalar {}: {} {:x?}", sender, opcode, args); + } + + fn blocking_scalar( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + args: [u32; 4], + ) -> ScalarResult { + panic!( + "Unhandled name blocking_scalar {}: {} {:x?}", + sender, opcode, args + ); + // ScalarResult::Scalar1(0) + } + + fn lend( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + buf: &[u8], + extra: [u32; 2], + ) -> LendResult { + panic!( + "Unhandled name lend {}: {} {:x?} {:x?}", + sender, opcode, buf, extra + ); + // LendResult::MemoryReturned([0, 0]) + } + + fn lend_mut( + &mut self, + memory: &mut Memory, + sender: u32, + opcode: u32, + buf: &mut [u8], + extra: [u32; 2], + ) -> LendResult { + if opcode == NameLendOpcode::Register as u32 { + panic!("Register opcode unimplemented"); + } else if opcode == NameLendOpcode::TryConnect as u32 + || opcode == NameLendOpcode::BlockingConnect as u32 + { + let buf_len = buf.len().min(extra[1] as usize); + let name = std::str::from_utf8(&buf[0..buf_len]).unwrap_or(""); + println!("Registering name {}", name); + + let service = Box::new(if name == "panic-to-screen!" { + println!("Panic-to-screen registered"); + super::panic_to_screen::PanicToScreen::new() + } else { + panic!("Unrecognized service name {}", name); + }); + + let connection_id = memory.connections.len() as u32 + 1; + memory.connections.insert(connection_id, service); + + buf[0..4].copy_from_slice(&0u32.to_le_bytes()); + buf[4..8].copy_from_slice(&connection_id.to_le_bytes()); + LendResult::MemoryReturned([0, 0]) + } else { + panic!( + "Unhandled name lend_mut {}: {} {:x?}", + sender, opcode, extra + ); + } + // + } + + fn send( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + _buf: &[u8], + extra: [u32; 2], + ) { + panic!("Unhandled name send {}: {} {:x?}", sender, opcode, extra); + } +} diff --git a/src/xous/services/panic_to_screen.rs b/src/xous/services/panic_to_screen.rs new file mode 100644 index 0000000..bb11c4d --- /dev/null +++ b/src/xous/services/panic_to_screen.rs @@ -0,0 +1,39 @@ +use super::{LendResult, Service}; +use crate::xous::Memory; + +enum PanicToScreenLendMutOpcode { + AppendPanicText = 0, +} + +pub struct PanicToScreen {} + +impl PanicToScreen { + pub fn new() -> Self { + PanicToScreen {} + } +} + +impl Default for PanicToScreen { + fn default() -> Self { + Self::new() + } +} + +impl Service for PanicToScreen { + fn lend_mut( + &mut self, + _memory: &mut Memory, + _sender: u32, + opcode: u32, + buf: &mut [u8], + extra: [u32; 2], + ) -> LendResult { + if opcode != PanicToScreenLendMutOpcode::AppendPanicText as _ { + panic!("Unhandled panic-to-screen opcode {}", opcode); + } + + let panic_str = std::str::from_utf8(&buf[0..extra[1] as usize]).unwrap_or(""); + println!("Panic to screen: {}", panic_str); + LendResult::MemoryReturned([0, 0]) + } +} diff --git a/src/xous/services/ticktimer.rs b/src/xous/services/ticktimer.rs index 1077c67..2ef10af 100644 --- a/src/xous/services/ticktimer.rs +++ b/src/xous/services/ticktimer.rs @@ -5,6 +5,7 @@ use std::{ }; use super::LendResult; +use crate::xous::Memory; pub struct Ticktimer { start: std::time::SystemTime, @@ -35,16 +36,24 @@ impl Default for Ticktimer { } impl super::Service for Ticktimer { - fn scalar(&mut self, _sender: u32, opcode: u32, args: [u32; 4]) { + fn scalar(&mut self, _memory: &mut Memory, _sender: u32, opcode: u32, args: [u32; 4]) { if opcode == ScalarOpcode::FreeCondition as u32 { let condition_index = args[0] as usize; if let Some(condvar) = self.condvars.remove(&condition_index) { assert!(condvar.1.load(std::sync::atomic::Ordering::Relaxed) == 0); } + } else { + println!("Unhandled scalar: {}", opcode); } } - fn blocking_scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) -> super::ScalarResult { + fn blocking_scalar( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + args: [u32; 4], + ) -> super::ScalarResult { if opcode == ScalarOpcode::ElapsedMs as u32 { let elapsed_ms = std::time::SystemTime::now() .duration_since(self.start) @@ -118,19 +127,27 @@ impl super::Service for Ticktimer { super::ScalarResult::Scalar1(notify_count as u32) } else { panic!( - "Ticktimer blocking_scalar {}: {} {:x?}", + "Ticktimer unhandled blocking_scalar {}: {} {:x?}", sender, opcode, args ); } } - fn lend(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) -> LendResult { + fn lend( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + _buf: &[u8], + extra: [u32; 2], + ) -> LendResult { println!("Ticktimer lend {}: {} {:x?}", sender, opcode, extra); LendResult::MemoryReturned([0, 0]) } fn lend_mut( &mut self, + _memory: &mut Memory, sender: u32, opcode: u32, _buf: &mut [u8], @@ -140,7 +157,14 @@ impl super::Service for Ticktimer { LendResult::MemoryReturned([0, 0]) } - fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) { + fn send( + &mut self, + _memory: &mut Memory, + sender: u32, + opcode: u32, + _buf: &[u8], + extra: [u32; 2], + ) { println!("Ticktimer send {}: {} {:x?}", sender, opcode, extra); } } diff --git a/src/xous/syscalls.rs b/src/xous/syscalls.rs index 25840f1..93e2ed3 100644 --- a/src/xous/syscalls.rs +++ b/src/xous/syscalls.rs @@ -1,3 +1,6 @@ +use std::sync::mpsc::channel; + +use super::super::xous::services::get_service; use super::definitions::{SyscallErrorNumber, SyscallResultNumber}; use super::services; use super::Memory; @@ -58,7 +61,7 @@ pub fn connect(memory: &mut Memory, id: [u32; 4]) -> SyscallResult { // "Connect([0x{:08x}, 0x{:08x}, 0x{:08x}, 0x{:08x}])", // id[0], id[1], id[2], id[3] // ); - if let Some(service) = super::super::xous::services::get_service(&id) { + if let Some(service) = get_service(&id) { let connection_id = memory.connections.len() as u32 + 1; memory.connections.insert(connection_id, service); [ @@ -91,7 +94,6 @@ pub fn try_connect(memory: &mut Memory, id: [u32; 4]) -> SyscallResult { connect(memory, id) } - pub fn send_message( memory: &mut Memory, connection_id: u32, @@ -116,11 +118,13 @@ pub fn send_message( } else { None }; - let Some(service) = memory.connections.get_mut(&connection_id) else { + // Pull the service out of the connections table so that we can send + // a mutable copy of the memory object to the service. + let Some(mut service) = memory.connections.remove(&connection_id) else { println!("Unhandled connection ID {}", connection_id); return [ SyscallResultNumber::Error as i64, - 9, /* ServerNotFound */ + SyscallErrorNumber::ServerNotFound as i64, 0, 0, 0, @@ -130,12 +134,12 @@ pub fn send_message( ] .into(); }; - match kind { + let response = match kind { 1..=3 => { let mut memory_region = memory_region.unwrap(); let extra = [args[2], args[3]]; match kind { - 1 => match service.lend_mut(0, opcode, &mut memory_region, extra) { + 1 => match service.lend_mut(memory, 0, opcode, &mut memory_region, extra) { services::LendResult::WaitForResponse(msg) => msg.into(), services::LendResult::MemoryReturned(result) => { for (offset, value) in memory_region.into_iter().enumerate() { @@ -154,7 +158,7 @@ pub fn send_message( .into() } }, - 2 => match service.lend(0, opcode, &memory_region, extra) { + 2 => match service.lend(memory, 0, opcode, &memory_region, extra) { services::LendResult::WaitForResponse(msg) => msg.into(), services::LendResult::MemoryReturned(result) => [ SyscallResultNumber::MemoryReturned as i64, @@ -169,17 +173,17 @@ pub fn send_message( .into(), }, 3 => { - service.send(0, opcode, &memory_region, extra); + service.send(memory, 0, opcode, &memory_region, extra); [SyscallResultNumber::Ok as i64, 0, 0, 0, 0, 0, 0, 0].into() } _ => unreachable!(), } } 4 => { - service.scalar(0, opcode, args); + service.scalar(memory, 0, opcode, args); [SyscallResultNumber::Ok as i64, 0, 0, 0, 0, 0, 0, 0].into() } - 5 => match service.blocking_scalar(0, opcode, args) { + 5 => match service.blocking_scalar(memory, 0, opcode, args) { services::ScalarResult::Scalar1(result) => [ SyscallResultNumber::Scalar1 as i64, result as i64, @@ -216,20 +220,22 @@ pub fn send_message( services::ScalarResult::WaitForResponse(msg) => msg.into(), }, _ => { - println!("Unknown message kind {}", kind); - [ - SyscallResultNumber::Error as i64, - 9, /* ServerNotFound */ - 0, - 0, - 0, - 0, - 0, - 0, - ] - .into() + panic!("Unknown message kind {}", kind); + // [ + // SyscallResultNumber::Error as i64, + // 9, /* ServerNotFound */ + // 0, + // 0, + // 0, + // 0, + // 0, + // 0, + // ] + // .into() } - } + }; + memory.connections.insert(connection_id, service); + response } pub fn try_send_message( @@ -294,3 +300,38 @@ pub fn increase_heap(memory: &mut Memory, delta: i64, _flags: i64) -> SyscallRes .into() } } + +pub fn create_thread( + memory: &mut Memory, + entry_point: i64, + stack_pointer: i64, + stack_length: i64, + arguments: [i64; 4], +) -> SyscallResult { + let (tx, rx) = channel(); + memory + .memory_cmd + .send(super::MemoryCommand::CreateThread( + entry_point as _, + stack_pointer as _, + stack_length as _, + arguments[0] as _, + arguments[1] as _, + arguments[2] as _, + arguments[3] as _, + tx, + )) + .unwrap(); + let thread_id = rx.recv().unwrap(); + [ + SyscallResultNumber::ThreadId as i64, + thread_id, + 0, + 0, + 0, + 0, + 0, + 0, + ] + .into() +}