mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-15 08:30:02 +00:00
kernel: get multiple message passing working
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
0ffbaa369a
commit
e652150c6e
7 changed files with 320 additions and 126 deletions
|
|
@ -29,7 +29,7 @@ enum BackchannelMessage {
|
|||
NewPid(PID),
|
||||
}
|
||||
|
||||
use std::net::{SocketAddr, IpAddr, Ipv4Addr};
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
thread_local!(static NETWORK_LISTEN_ADDRESS: RefCell<SocketAddr> = RefCell::new(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080)));
|
||||
|
||||
/// Set the network address for this particular thread.
|
||||
|
|
@ -54,10 +54,10 @@ fn handle_connection(mut conn: TcpStream, pid: PID, chn: Sender<ThreadMessage>)
|
|||
// If the connection has gone away, send a `TerminateProcess` message to the main
|
||||
// and then exit this thread.
|
||||
if e.kind() != std::io::ErrorKind::WouldBlock {
|
||||
// println!(
|
||||
// "KERNEL({}): Client disconnected: {}. Shutting down virtual process.",
|
||||
// pid, e
|
||||
// );
|
||||
println!(
|
||||
"KERNEL({}): Client disconnected: {} ({:?}). Shutting down virtual process.",
|
||||
pid, e, e
|
||||
);
|
||||
chn.send(ThreadMessage::SysCall(pid, xous::SysCall::TerminateProcess))
|
||||
.unwrap();
|
||||
return;
|
||||
|
|
@ -83,6 +83,7 @@ fn handle_connection(mut conn: TcpStream, pid: PID, chn: Sender<ThreadMessage>)
|
|||
tmp_data.resize(msg.buf.len(), 0);
|
||||
conn.read_exact(&mut tmp_data)
|
||||
.map_err(|_e| {
|
||||
println!("KERNEL({}): Read Error {}", pid, _e);
|
||||
chn.send(ThreadMessage::SysCall(
|
||||
pid,
|
||||
xous::SysCall::TerminateProcess,
|
||||
|
|
@ -216,12 +217,13 @@ pub fn idle() -> bool {
|
|||
let (sender, receiver) = channel();
|
||||
let (backchannel_sender, backchannel_receiver) = channel();
|
||||
|
||||
let listen_addr = env::var("XOUS_LISTEN_ADDR").map(|s|
|
||||
s
|
||||
.to_socket_addrs()
|
||||
.expect("invalid server address")
|
||||
.next()
|
||||
.expect("unable to resolve server address"))
|
||||
let listen_addr = env::var("XOUS_LISTEN_ADDR")
|
||||
.map(|s| {
|
||||
s.to_socket_addrs()
|
||||
.expect("invalid server address")
|
||||
.next()
|
||||
.expect("unable to resolve server address")
|
||||
})
|
||||
.unwrap_or_else(|_| NETWORK_LISTEN_ADDRESS.with(|nla| *nla.borrow()));
|
||||
|
||||
let listen_thread_handle =
|
||||
|
|
@ -230,19 +232,26 @@ pub fn idle() -> bool {
|
|||
while let Ok(msg) = receiver.recv() {
|
||||
match msg {
|
||||
ThreadMessage::NewConnection(conn) => {
|
||||
// println!("KERNEL(?): Going to call ss.spawn_process()");
|
||||
// Spawn a new process inside the kernel. This will assign us a PID.
|
||||
let new_pid = SystemServices::with_mut(|ss| {
|
||||
ss.spawn_process(process::ProcessInit::new(conn.try_clone().unwrap()), ())
|
||||
})
|
||||
.unwrap();
|
||||
// println!("KERNEL({}): SystemServices assigned new PID of {}", new_pid, new_pid);
|
||||
|
||||
// Inform the backchannel of the new process ID.
|
||||
backchannel_sender
|
||||
.send(BackchannelMessage::NewPid(new_pid))
|
||||
.expect("couldn't send new pid to new connection");
|
||||
|
||||
// Switch to this process immediately, which moves it from `Setup(_)` to `Running(0)`.
|
||||
// Note that in this system, multiple processes can be active at once. This is
|
||||
// similar to having one core for each process. However, each process may only have
|
||||
// one context running at a time.
|
||||
SystemServices::with_mut(|ss| ss.switch_to(new_pid, Some(1))).unwrap();
|
||||
}
|
||||
ThreadMessage::SysCall(pid, call) => {
|
||||
// println!("KERNEL({}): Received syscall {:?}", pid, call);
|
||||
SystemServices::with_mut(|ss| ss.switch_to(pid, Some(1))).unwrap();
|
||||
println!("KERNEL({}): Received syscall {:?}", pid, call);
|
||||
crate::arch::process::set_current_pid(pid);
|
||||
// println!("KERNEL({}): Now running as the new process", pid);
|
||||
|
||||
// If the call being made is to terminate the current process, we need to know
|
||||
|
|
@ -271,11 +280,18 @@ pub fn idle() -> bool {
|
|||
// Handle the syscall within the Xous kernel
|
||||
let response = crate::syscall::handle(pid, call).unwrap_or_else(Result::Error);
|
||||
|
||||
// println!("KERNEL({}): Syscall response {:?}", pid, response);
|
||||
println!("KERNEL({}): Syscall response {:?}", pid, response);
|
||||
// There's a response if it wasn't a blocked process and we're not terminating.
|
||||
// Send the response back to the target.
|
||||
if response != Result::BlockedProcess && !is_terminate && !is_shutdown {
|
||||
{
|
||||
// The syscall may change what the current process is, but we always
|
||||
// want to send a response to the process where the request came from.
|
||||
// For this block, switch to the original PID, send the message, then
|
||||
// switch back.
|
||||
let existing_pid = crate::arch::process::current_pid();
|
||||
crate::arch::process::set_current_pid(pid);
|
||||
|
||||
let mut process = Process::current();
|
||||
let mut response_vec = Vec::new();
|
||||
for word in response.to_args().iter_mut() {
|
||||
|
|
@ -289,8 +305,11 @@ pub fn idle() -> bool {
|
|||
// );
|
||||
crate::syscall::handle(pid, SysCall::TerminateProcess).ok();
|
||||
});
|
||||
crate::arch::process::set_current_pid(existing_pid);
|
||||
}
|
||||
SystemServices::with_mut(|ss| ss.switch_from(pid, 1, true)).unwrap();
|
||||
// SystemServices::with_mut(|ss| {
|
||||
// println!("295: Switching from {}", pid);
|
||||
// ss.switch_from(pid, 1, true)}).unwrap();
|
||||
}
|
||||
|
||||
if is_shutdown {
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ impl Process {
|
|||
}
|
||||
|
||||
pub fn set_context_result(&mut self, context: CtxID, result: xous::Result) {
|
||||
assert!(context == INITIAL_CONTEXT);
|
||||
assert!(context == INITIAL_CONTEXT, "context is {} and not {}", context, INITIAL_CONTEXT);
|
||||
let mut response = vec![];
|
||||
for word in result.to_args().iter_mut() {
|
||||
response.extend_from_slice(&word.to_le_bytes());
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
pub use crate::arch::process::Context;
|
||||
use core::mem;
|
||||
use xous::{CtxID, MemoryAddress, MemoryRange, MemorySize, Message, PID, SID, pid_from_usize};
|
||||
use xous::{CtxID, MemoryAddress, MemoryRange, MemorySize, Message, PID, SID};
|
||||
|
||||
pub struct SenderID {
|
||||
pub sidx: usize,
|
||||
|
|
@ -17,7 +17,6 @@ impl SenderID {
|
|||
}
|
||||
|
||||
pub enum WaitingMessage {
|
||||
|
||||
/// There is no waiting message.
|
||||
None,
|
||||
|
||||
|
|
@ -38,7 +37,8 @@ pub enum WaitingMessage {
|
|||
enum QueuedMessage {
|
||||
Empty,
|
||||
ScalarMessage(
|
||||
usize, /* sender PID/CtxID */
|
||||
u16, /* sender PID */
|
||||
u16, /* Sender CTX */
|
||||
usize, /* sender base address */
|
||||
usize, /* id */
|
||||
usize, /* arg1 */
|
||||
|
|
@ -47,7 +47,8 @@ enum QueuedMessage {
|
|||
usize, /* arg4 */
|
||||
),
|
||||
MemoryMessageSend(
|
||||
usize, /* sender PID/CtxID */
|
||||
u16, /* sender PID */
|
||||
u16, /* Sender CTX */
|
||||
usize, /* reserved */
|
||||
usize, /* id */
|
||||
usize, /* buf */
|
||||
|
|
@ -56,7 +57,8 @@ enum QueuedMessage {
|
|||
usize, /* valid */
|
||||
),
|
||||
MemoryMessageROLend(
|
||||
usize, /* sender PID/CtxID */
|
||||
u16, /* sender PID */
|
||||
u16, /* Sender CTX */
|
||||
usize, /* sender base address */
|
||||
usize, /* id */
|
||||
usize, /* buf */
|
||||
|
|
@ -65,7 +67,8 @@ enum QueuedMessage {
|
|||
usize, /* valid */
|
||||
),
|
||||
MemoryMessageRWLend(
|
||||
usize, /* sender PID/CtxID */
|
||||
u16, /* sender PID */
|
||||
u16, /* Sender CTX */
|
||||
usize, /* sender base address */
|
||||
usize, /* id */
|
||||
usize, /* buf */
|
||||
|
|
@ -77,7 +80,8 @@ enum QueuedMessage {
|
|||
/// The process lending this memory terminated before
|
||||
/// we could receive the message.
|
||||
MemoryMessageROLendTerminated(
|
||||
usize, /* sender PID/CtxID */
|
||||
u16, /* sender PID */
|
||||
u16, /* Sender CTX */
|
||||
usize, /* sender base address */
|
||||
usize, /* id */
|
||||
usize, /* buf */
|
||||
|
|
@ -89,7 +93,8 @@ enum QueuedMessage {
|
|||
/// The process lending this memory terminated before
|
||||
/// we could receive the message.
|
||||
MemoryMessageRWLendTerminated(
|
||||
usize, /* sender PID/CtxID */
|
||||
u16, /* sender PID */
|
||||
u16, /* Sender CTX */
|
||||
usize, /* sender base address */
|
||||
usize, /* id */
|
||||
usize, /* buf */
|
||||
|
|
@ -103,7 +108,8 @@ enum QueuedMessage {
|
|||
/// index is returned as the message sender. This is used to unblock the
|
||||
/// sending process.
|
||||
WaitingResponse(
|
||||
usize, /* sender PID/CtxID */
|
||||
u16, /* sender PID */
|
||||
u16, /* Sender CTX */
|
||||
usize, /* Client base address */
|
||||
usize, /* Server base address */
|
||||
usize, /* Range size */
|
||||
|
|
@ -112,7 +118,8 @@ enum QueuedMessage {
|
|||
/// When a server goes away, its memory must be forgotten instead of being returned
|
||||
/// to the previous process.
|
||||
WaitingForget(
|
||||
usize, /* sender PID/CtxID */
|
||||
u16, /* sender PID */
|
||||
u16, /* Sender CTX */
|
||||
usize, /* Client base address */
|
||||
usize, /* Server base address */
|
||||
usize, /* Range size */
|
||||
|
|
@ -143,6 +150,11 @@ pub struct Server {
|
|||
ready_contexts: usize,
|
||||
}
|
||||
|
||||
/// Convert a PID and CTX pair into a `usize` sender
|
||||
fn make_sender(pid: u16, ctx: u16) -> usize {
|
||||
(((pid as usize) << 16) & 0xffff_0000) | (ctx as usize & 0xffff)
|
||||
}
|
||||
|
||||
impl Server {
|
||||
/// Initialize a server in the given option array. This function is
|
||||
/// designed to be called with `new` pointing to an entry in a vec.
|
||||
|
|
@ -185,9 +197,7 @@ impl Server {
|
|||
}
|
||||
|
||||
/// Take a current slot and replace it with `None`, clearing out the contents of the queue.
|
||||
pub fn destroy(
|
||||
current: &mut Option<Server>
|
||||
) -> Result<(), xous::Error> {
|
||||
pub fn destroy(current: &mut Option<Server>) -> Result<(), xous::Error> {
|
||||
*current = None;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -208,18 +218,36 @@ impl Server {
|
|||
pub fn discard_messages_for_pid(&mut self, pid: PID) {
|
||||
for entry in self.queue.iter_mut() {
|
||||
match entry {
|
||||
&mut QueuedMessage::MemoryMessageROLend(pid_ctx, arg1, arg2, arg3, arg4, arg5, arg6) => {
|
||||
if let Ok(msg_pid) = pid_from_usize(pid_ctx >> 16) {
|
||||
if msg_pid == pid {
|
||||
*entry = QueuedMessage::MemoryMessageROLendTerminated(pid_ctx, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
&mut QueuedMessage::MemoryMessageROLend(
|
||||
msg_pid,
|
||||
ctx,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
arg4,
|
||||
arg5,
|
||||
arg6,
|
||||
) => {
|
||||
if msg_pid == pid.get() as _ {
|
||||
*entry = QueuedMessage::MemoryMessageROLendTerminated(
|
||||
msg_pid, ctx, arg1, arg2, arg3, arg4, arg5, arg6,
|
||||
);
|
||||
}
|
||||
}
|
||||
&mut QueuedMessage::MemoryMessageRWLend(pid_ctx, arg1, arg2, arg3, arg4, arg5, arg6) => {
|
||||
if let Ok(msg_pid) = pid_from_usize(pid_ctx >> 16) {
|
||||
if msg_pid == pid {
|
||||
*entry = QueuedMessage::MemoryMessageRWLendTerminated(pid_ctx, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
&mut QueuedMessage::MemoryMessageRWLend(
|
||||
msg_pid,
|
||||
ctx,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
arg4,
|
||||
arg5,
|
||||
arg6,
|
||||
) => {
|
||||
if msg_pid == pid.get() as _ {
|
||||
*entry = QueuedMessage::MemoryMessageRWLendTerminated(
|
||||
msg_pid, ctx, arg1, arg2, arg3, arg4, arg5, arg6,
|
||||
);
|
||||
}
|
||||
}
|
||||
// For "Scalar" and "Move" messages, this memory has already
|
||||
|
|
@ -234,16 +262,20 @@ impl Server {
|
|||
/// and return the pair. Advance the tail. Note that the `idx` could be
|
||||
/// somewhere other than the tail, but as long as it points to a valid
|
||||
/// message that's waiting a response, that's acceptable.
|
||||
pub fn take_waiting_message(&mut self, idx: usize, buf: MemoryRange) -> Result<WaitingMessage, xous::Error> {
|
||||
pub fn take_waiting_message(
|
||||
&mut self,
|
||||
idx: usize,
|
||||
buf: MemoryRange,
|
||||
) -> Result<WaitingMessage, xous::Error> {
|
||||
if idx > self.queue.len() {
|
||||
return Err(xous::Error::BadAddress);
|
||||
}
|
||||
let (pid_ctx, server_addr, client_addr, len, forget) = match self.queue[idx] {
|
||||
QueuedMessage::WaitingResponse(pid_ctx, server_addr, client_addr, len) => {
|
||||
(pid_ctx, server_addr, client_addr, len, false)
|
||||
let (pid, ctx, server_addr, client_addr, len, forget) = match self.queue[idx] {
|
||||
QueuedMessage::WaitingResponse(pid, ctx, server_addr, client_addr, len) => {
|
||||
(pid, ctx, server_addr, client_addr, len, false)
|
||||
}
|
||||
QueuedMessage::WaitingForget(pid_ctx, server_addr, client_addr, len) => {
|
||||
(pid_ctx, server_addr, client_addr, len, true)
|
||||
QueuedMessage::WaitingForget(pid, ctx, server_addr, client_addr, len) => {
|
||||
(pid, ctx, server_addr, client_addr, len, true)
|
||||
}
|
||||
_ => return Ok(WaitingMessage::None),
|
||||
};
|
||||
|
|
@ -257,11 +289,13 @@ impl Server {
|
|||
}
|
||||
|
||||
// Destructure the PID and context ID from the `pid_ctx` field
|
||||
let pid = pid_from_usize((pid_ctx >> 16) & 0xff)?;
|
||||
let ctx = (pid_ctx & 0xffff) as CtxID;
|
||||
println!("Taking waiting message -- pid: {} ctx: {}", pid, ctx);
|
||||
|
||||
if forget {
|
||||
return Ok(WaitingMessage::ForgetMemory(MemoryRange::new(server_addr, len)));
|
||||
return Ok(WaitingMessage::ForgetMemory(MemoryRange::new(
|
||||
server_addr,
|
||||
len,
|
||||
)));
|
||||
}
|
||||
|
||||
// If a `move` address somehow ends up here, indicate the memory has been moved.
|
||||
|
|
@ -274,8 +308,8 @@ impl Server {
|
|||
.expect("client memory address was 0, but server address was not");
|
||||
let len = MemorySize::new(len).expect("memory length was 0, but address was not None");
|
||||
Ok(WaitingMessage::BorrowedMemory(
|
||||
pid,
|
||||
ctx,
|
||||
PID::new(pid as _).unwrap(),
|
||||
ctx as _,
|
||||
server_addr,
|
||||
client_addr,
|
||||
len,
|
||||
|
|
@ -299,10 +333,11 @@ impl Server {
|
|||
// );
|
||||
let result = match self.queue[self.queue_tail] {
|
||||
QueuedMessage::Empty => return None,
|
||||
QueuedMessage::WaitingResponse(_, _, _, _) => return None,
|
||||
QueuedMessage::WaitingForget(_, _, _, _) => return None,
|
||||
QueuedMessage::WaitingResponse(_, _, _, _, _) => return None,
|
||||
QueuedMessage::WaitingForget(_, _, _, _, _) => return None,
|
||||
QueuedMessage::MemoryMessageROLend(
|
||||
pid_ctx,
|
||||
pid,
|
||||
ctx,
|
||||
client_addr,
|
||||
id,
|
||||
buf,
|
||||
|
|
@ -319,14 +354,16 @@ impl Server {
|
|||
valid: MemorySize::new(valid),
|
||||
}),
|
||||
},
|
||||
pid_ctx,
|
||||
pid,
|
||||
ctx,
|
||||
buf,
|
||||
client_addr,
|
||||
buf_size,
|
||||
false,
|
||||
),
|
||||
QueuedMessage::MemoryMessageRWLend(
|
||||
pid_ctx,
|
||||
pid,
|
||||
ctx,
|
||||
client_addr,
|
||||
id,
|
||||
buf,
|
||||
|
|
@ -343,14 +380,16 @@ impl Server {
|
|||
valid: MemorySize::new(valid),
|
||||
}),
|
||||
},
|
||||
pid_ctx,
|
||||
pid,
|
||||
ctx,
|
||||
buf,
|
||||
client_addr,
|
||||
buf_size,
|
||||
false,
|
||||
),
|
||||
QueuedMessage::MemoryMessageROLendTerminated(
|
||||
pid_ctx,
|
||||
pid,
|
||||
ctx,
|
||||
client_addr,
|
||||
id,
|
||||
buf,
|
||||
|
|
@ -367,14 +406,16 @@ impl Server {
|
|||
valid: MemorySize::new(valid),
|
||||
}),
|
||||
},
|
||||
pid_ctx,
|
||||
pid,
|
||||
ctx,
|
||||
buf,
|
||||
client_addr,
|
||||
buf_size,
|
||||
true,
|
||||
),
|
||||
QueuedMessage::MemoryMessageRWLendTerminated(
|
||||
pid_ctx,
|
||||
pid,
|
||||
ctx,
|
||||
client_addr,
|
||||
id,
|
||||
buf,
|
||||
|
|
@ -391,14 +432,16 @@ impl Server {
|
|||
valid: MemorySize::new(valid),
|
||||
}),
|
||||
},
|
||||
pid_ctx,
|
||||
pid,
|
||||
ctx,
|
||||
buf,
|
||||
client_addr,
|
||||
buf_size,
|
||||
true,
|
||||
),
|
||||
QueuedMessage::MemoryMessageSend(
|
||||
pid_ctx,
|
||||
pid,
|
||||
ctx,
|
||||
_reserved,
|
||||
id,
|
||||
buf,
|
||||
|
|
@ -407,7 +450,7 @@ impl Server {
|
|||
valid,
|
||||
) => {
|
||||
let msg = xous::MessageEnvelope {
|
||||
sender: pid_ctx,
|
||||
sender: make_sender(pid, ctx),
|
||||
message: xous::Message::Move(xous::MemoryMessage {
|
||||
id,
|
||||
buf: MemoryRange::new(buf, buf_size),
|
||||
|
|
@ -424,9 +467,9 @@ impl Server {
|
|||
}
|
||||
|
||||
// Scalar messages have nothing to return, so they can go straight to the `Free` state
|
||||
QueuedMessage::ScalarMessage(pid_ctx, _reserved, id, arg1, arg2, arg3, arg4) => {
|
||||
QueuedMessage::ScalarMessage(pid, ctx, _reserved, id, arg1, arg2, arg3, arg4) => {
|
||||
let msg = xous::MessageEnvelope {
|
||||
sender: pid_ctx,
|
||||
sender: make_sender(pid, ctx),
|
||||
message: xous::Message::Scalar(xous::ScalarMessage {
|
||||
id,
|
||||
arg1,
|
||||
|
|
@ -443,12 +486,12 @@ impl Server {
|
|||
return Some(msg);
|
||||
}
|
||||
};
|
||||
if result.5 {
|
||||
if result.6 {
|
||||
self.queue[self.queue_tail] =
|
||||
QueuedMessage::WaitingForget(result.1, result.2, result.3, result.4);
|
||||
QueuedMessage::WaitingForget(result.1, result.2, result.3, result.4, result.5);
|
||||
} else {
|
||||
self.queue[self.queue_tail] =
|
||||
QueuedMessage::WaitingResponse(result.1, result.2, result.3, result.4);
|
||||
QueuedMessage::WaitingResponse(result.1, result.2, result.3, result.4, result.5);
|
||||
}
|
||||
Some(result.0)
|
||||
}
|
||||
|
|
@ -472,7 +515,8 @@ impl Server {
|
|||
|
||||
self.queue[self.queue_head] = match message {
|
||||
xous::Message::Scalar(msg) => QueuedMessage::ScalarMessage(
|
||||
pid.get() as usize | (context << 16),
|
||||
pid.get() as _,
|
||||
context as _,
|
||||
original_address.map(|x| x.get()).unwrap_or(0),
|
||||
msg.id,
|
||||
msg.arg1,
|
||||
|
|
@ -481,7 +525,8 @@ impl Server {
|
|||
msg.arg4,
|
||||
),
|
||||
xous::Message::Move(msg) => QueuedMessage::MemoryMessageSend(
|
||||
pid.get() as usize | (context << 16),
|
||||
pid.get() as _,
|
||||
context as _,
|
||||
original_address.map(|x| x.get()).unwrap_or(0),
|
||||
msg.id,
|
||||
msg.buf.addr.get(),
|
||||
|
|
@ -490,7 +535,8 @@ impl Server {
|
|||
msg.valid.map(|x| x.get()).unwrap_or(0) as usize,
|
||||
),
|
||||
xous::Message::MutableBorrow(msg) => QueuedMessage::MemoryMessageRWLend(
|
||||
pid.get() as usize | (context << 16),
|
||||
pid.get() as _,
|
||||
context as _,
|
||||
original_address.map(|x| x.get()).unwrap_or(0),
|
||||
msg.id,
|
||||
msg.buf.addr.get(),
|
||||
|
|
@ -499,7 +545,8 @@ impl Server {
|
|||
msg.valid.map(|x| x.get()).unwrap_or(0) as usize,
|
||||
),
|
||||
xous::Message::Borrow(msg) => QueuedMessage::MemoryMessageROLend(
|
||||
pid.get() as usize | (context << 16),
|
||||
pid.get() as _,
|
||||
context as _,
|
||||
original_address.map(|x| x.get()).unwrap_or(0),
|
||||
msg.id,
|
||||
msg.buf.addr.get(),
|
||||
|
|
@ -536,7 +583,8 @@ impl Server {
|
|||
};
|
||||
|
||||
self.queue[self.queue_head] = QueuedMessage::WaitingResponse(
|
||||
((pid.get() as usize) << 16) | (context & 0xffff),
|
||||
pid.get() as _,
|
||||
context as _,
|
||||
server_address,
|
||||
client_address.map(|x| x.get()).unwrap_or(0),
|
||||
len,
|
||||
|
|
@ -568,6 +616,10 @@ impl Server {
|
|||
// If the context mask matches this context number, remove it
|
||||
// and return the index.
|
||||
if self.ready_contexts & test_ctx_mask == test_ctx_mask {
|
||||
println!(
|
||||
"Returning ready context {:08b}: {}",
|
||||
self.ready_contexts, ctx_number
|
||||
);
|
||||
self.ready_contexts &= !test_ctx_mask;
|
||||
return Some(ctx_number);
|
||||
}
|
||||
|
|
@ -599,7 +651,7 @@ impl Server {
|
|||
|
||||
/// Add the given context to the list of ready and waiting contexts.
|
||||
pub fn park_context(&mut self, context: CtxID) {
|
||||
// println!("Parking context: {}", context);
|
||||
println!("KERNEL({}): Parking context: {}", self.pid, context);
|
||||
self.ready_contexts |= 1 << context;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ pub use crate::arch::process::INITIAL_CONTEXT;
|
|||
/// This is inherited from the stage 1 bootloader.
|
||||
pub struct SystemServices {
|
||||
/// Current PID.
|
||||
pid: PID,
|
||||
// pid: PID,
|
||||
|
||||
/// A table of all processes in the system
|
||||
pub processes: [Process; MAX_PROCESS_COUNT],
|
||||
|
|
@ -193,7 +193,7 @@ impl Process {
|
|||
}
|
||||
|
||||
thread_local!(static SYSTEM_SERVICES: RefCell<SystemServices> = RefCell::new(SystemServices {
|
||||
pid: unsafe { PID::new_unchecked(1) },
|
||||
// pid: unsafe { PID::new_unchecked(1) },
|
||||
processes: [Process {
|
||||
state: ProcessState::Free,
|
||||
ppid: unsafe { PID::new_unchecked(1) },
|
||||
|
|
@ -299,6 +299,7 @@ impl SystemServices {
|
|||
let new_pid = pid_from_usize(idx + 1)?;
|
||||
arch::process::Process::create(new_pid, init_process);
|
||||
// #[allow(clippy::unit_arg)]
|
||||
println!("Creating new process for PID {}", new_pid);
|
||||
entry.state = ProcessState::Setup(init_context);
|
||||
entry.ppid = crate::arch::process::current_pid();
|
||||
entry.pid = new_pid;
|
||||
|
|
@ -336,8 +337,8 @@ impl SystemServices {
|
|||
Ok(&mut self.processes[pid_idx])
|
||||
}
|
||||
|
||||
pub fn current_context_nr(&self) -> usize {
|
||||
self.processes[self.pid.get() as usize - 1].current_context as usize
|
||||
pub fn current_context_nr(&self, pid: PID) -> usize {
|
||||
self.processes[pid.get() as usize - 1].current_context as usize
|
||||
}
|
||||
|
||||
pub fn current_pid(&self) -> PID {
|
||||
|
|
@ -403,7 +404,7 @@ impl SystemServices {
|
|||
let mut arch_process = crate::arch::process::Process::current();
|
||||
arch_process.set_context(context)?;
|
||||
}
|
||||
self.pid = pid;
|
||||
// self.pid = pid;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -480,6 +481,7 @@ impl SystemServices {
|
|||
/// Mark the specified context as ready to run. If the thread is Sleeping, mark
|
||||
/// it as Ready.
|
||||
pub fn ready_context(&mut self, pid: PID, context: CtxID) -> Result<(), xous::Error> {
|
||||
assert!(context == INITIAL_CONTEXT);
|
||||
let process = self.get_process_mut(pid)?;
|
||||
process.state = match process.state {
|
||||
ProcessState::Free => panic!(
|
||||
|
|
@ -498,6 +500,7 @@ impl SystemServices {
|
|||
pid, context, other
|
||||
),
|
||||
};
|
||||
println!("KERNEL({}): Readying context {} -> {:?}", pid, context, process.state);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -510,6 +513,7 @@ impl SystemServices {
|
|||
// println!("KERNEL(?): Getting current process...");
|
||||
let process = self.get_process_mut(pid)?;
|
||||
// println!("KERNEL(?): Current process is {:?}", process);
|
||||
println!("switch_to (start): PID {}: {:?} @ {:?}", pid, process.state, std::thread::current().id());
|
||||
|
||||
// Determine which context number to switch to
|
||||
process.state = match process.state {
|
||||
|
|
@ -530,6 +534,7 @@ impl SystemServices {
|
|||
let mut p = crate::arch::process::Process::current();
|
||||
p.setup_context(INITIAL_CONTEXT, setup)?;
|
||||
p.set_context(INITIAL_CONTEXT)?;
|
||||
process.current_context = INITIAL_CONTEXT as u8;
|
||||
|
||||
// Mark the current proces state as "running, and no waiting contexts"
|
||||
ProcessState::Running(0)
|
||||
|
|
@ -609,7 +614,8 @@ impl SystemServices {
|
|||
ProcessState::Running(new_mask)
|
||||
}
|
||||
};
|
||||
self.pid = pid;
|
||||
println!("switch_to (end): PID {}: {:?}", pid, process.state);
|
||||
// self.pid = pid;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -628,6 +634,7 @@ impl SystemServices {
|
|||
can_resume: bool,
|
||||
) -> Result<(), xous::Error> {
|
||||
let process = self.get_process_mut(pid)?;
|
||||
println!("switch_from (start): PID {}: {:?}", pid, process.state);
|
||||
process.state = match process.state {
|
||||
ProcessState::Running(x) if x & (1 << context) != 0 => panic!(
|
||||
"PID {} context {} was already queued for running when `switch_from()` was called",
|
||||
|
|
@ -649,6 +656,7 @@ impl SystemServices {
|
|||
pid, other
|
||||
),
|
||||
};
|
||||
println!("switch_from (end): PID {}: {:?}", pid, process.state);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -685,9 +693,10 @@ impl SystemServices {
|
|||
can_resume: bool,
|
||||
advance_context: bool,
|
||||
) -> Result<CtxID, xous::Error> {
|
||||
println!("Activating PID {}, context {}", new_pid, new_context);
|
||||
// println!("Activating PID {}, context {}", new_pid, new_context);
|
||||
let previous_pid = self.current_pid();
|
||||
let previous_context = self.current_context_nr();
|
||||
let previous_context = self.current_context_nr(previous_pid);
|
||||
println!("KERNEL({}): Activating process {} context {}", previous_pid, new_pid, new_context);
|
||||
|
||||
// Save state if the PID has changed. This will activate the new memory
|
||||
// space.
|
||||
|
|
@ -814,7 +823,7 @@ impl SystemServices {
|
|||
// previous_pid, previous.state, can_resume
|
||||
// );
|
||||
} else {
|
||||
if self.current_context_nr() == new_context {
|
||||
if self.current_context_nr(previous_pid) == new_context {
|
||||
if !can_resume {
|
||||
panic!("tried to switch to our own context without resume");
|
||||
}
|
||||
|
|
@ -844,13 +853,13 @@ impl SystemServices {
|
|||
}
|
||||
}
|
||||
}
|
||||
self.pid = new_pid;
|
||||
// self.pid = new_pid;
|
||||
|
||||
let mut process = crate::arch::process::Process::current();
|
||||
|
||||
// Restore the previous context, if one exists.
|
||||
process.set_context(new_context)?;
|
||||
self.processes[self.pid.get() as usize - 1].current_context = new_context as u8;
|
||||
self.processes[new_pid.get() as usize - 1].current_context = new_context as u8;
|
||||
// let _ctx = process.current_context();
|
||||
|
||||
Ok(new_context)
|
||||
|
|
@ -1186,7 +1195,7 @@ impl SystemServices {
|
|||
/// queue.
|
||||
/// * **ServerNotFound**: The server queue was full and a free slot could not
|
||||
/// be found.
|
||||
pub fn create_server(&mut self, name: usize) -> Result<SID, xous::Error> {
|
||||
pub fn create_server(&mut self, pid: PID, name: usize) -> Result<SID, xous::Error> {
|
||||
// println!(
|
||||
// "KERNEL({}): Looking through server list for free server",
|
||||
// self.pid.get()
|
||||
|
|
@ -1198,7 +1207,6 @@ impl SystemServices {
|
|||
// "KERNEL({}): Found a free slot for a server -- allocating an entry",
|
||||
// self.pid.get()
|
||||
// );
|
||||
let pid = self.pid;
|
||||
|
||||
// TODO: Come up with a way to randomize this
|
||||
let sid = (
|
||||
|
|
@ -1415,6 +1423,7 @@ impl SystemServices {
|
|||
process.activate()?;
|
||||
let parent_pid = process.ppid;
|
||||
process.terminate()?;
|
||||
println!("KERNEL({}): Terminated", target_pid);
|
||||
|
||||
let process = self.get_process(parent_pid)?;
|
||||
process.activate().unwrap();
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
}
|
||||
SysCall::SwitchTo(new_pid, new_context) => {
|
||||
SystemServices::with_mut(|ss| {
|
||||
let context_nr = ss.current_context_nr();
|
||||
let context_nr = ss.current_context_nr(pid);
|
||||
unsafe {
|
||||
assert!(
|
||||
SWITCHTO_CALLER.is_none(),
|
||||
|
|
@ -187,7 +187,7 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
SysCall::ReceiveMessage(sid) => {
|
||||
SystemServices::with_mut(|ss| {
|
||||
// See if there is a pending message. If so, return immediately.
|
||||
let context_nr = ss.current_context_nr();
|
||||
let context_nr = ss.current_context_nr(pid);
|
||||
let sidx = ss.server_sidx(sid).ok_or(xous::Error::ServerNotFound)?;
|
||||
let server = ss
|
||||
.server_from_sidx(sidx)
|
||||
|
|
@ -209,10 +209,10 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
// process and mark ourselves as awaiting an event. When a message
|
||||
// arrives, our return value will already be set to the
|
||||
// MessageEnvelope of the incoming message.
|
||||
// println!(
|
||||
// "PID {} did not have any waiting messages -- parking context {}",
|
||||
// pid, context_nr
|
||||
// );
|
||||
println!(
|
||||
"KERNEL({}): did not have any waiting messages -- parking context {}",
|
||||
pid, context_nr
|
||||
);
|
||||
server.park_context(context_nr);
|
||||
|
||||
// For baremetal targets, switch away from this process.
|
||||
|
|
@ -226,6 +226,7 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
// For hosted targets, simply return `BlockedProcess` indicating we'll make
|
||||
// a callback to their socket at a later time.
|
||||
else {
|
||||
println!("229: Switching from {}", pid);
|
||||
ss.switch_from(pid, context_nr, false)
|
||||
.map(|_| xous::Result::BlockedProcess)
|
||||
}
|
||||
|
|
@ -246,7 +247,7 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
})
|
||||
}
|
||||
SysCall::CreateServer(name) => {
|
||||
SystemServices::with_mut(|ss| ss.create_server(name).map(xous::Result::ServerID))
|
||||
SystemServices::with_mut(|ss| ss.create_server(pid, name).map(xous::Result::ServerID))
|
||||
}
|
||||
SysCall::Connect(sid) => {
|
||||
// ::debug_here::debug_here!();
|
||||
|
|
@ -296,15 +297,15 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
return Err(xous::Error::ProcessNotFound);
|
||||
}
|
||||
};
|
||||
// println!(
|
||||
// "Returning {} bytes from {:08x} in PID {} to {:08x} in PID {} in context {}",
|
||||
// len,
|
||||
// server_addr.get(),
|
||||
// pid,
|
||||
// client_addr.get(),
|
||||
// client_pid,
|
||||
// client_ctx
|
||||
// );
|
||||
println!(
|
||||
"Returning {} bytes from {:08x} in PID {} to {:08x} in PID {} in context {}",
|
||||
len,
|
||||
server_addr.get(),
|
||||
pid,
|
||||
client_addr.get(),
|
||||
client_pid,
|
||||
client_ctx
|
||||
);
|
||||
|
||||
// Return the memory to the calling process
|
||||
ss.return_memory(
|
||||
|
|
@ -315,15 +316,19 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
)?;
|
||||
|
||||
// Unblock the client context to allow it to continue.
|
||||
// println!("Unblocking PID {} CTX {}", client_pid, client_ctx);
|
||||
println!(
|
||||
"KERNEL({}): Unblocking PID {} CTX {}",
|
||||
pid, client_pid, client_ctx
|
||||
);
|
||||
ss.ready_context(client_pid, client_ctx)?;
|
||||
ss.set_context_result(client_pid, client_ctx, xous::Result::Ok)?;
|
||||
ss.switch_to(client_pid, Some(client_ctx))?;
|
||||
Ok(xous::Result::Ok)
|
||||
})
|
||||
}
|
||||
SysCall::SendMessage(cid, message) => {
|
||||
SystemServices::with_mut(|ss| {
|
||||
let context_nr = ss.current_context_nr();
|
||||
let context_nr = ss.current_context_nr(pid);
|
||||
let sidx = ss.sidx_from_cid(cid).ok_or(xous::Error::ServerNotFound)?;
|
||||
// ::debug_here::debug_here!();
|
||||
|
||||
|
|
@ -455,11 +460,16 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
.unwrap_or(Err(xous::Error::ProcessNotFound))
|
||||
} else if blocking && !cfg!(baremetal) {
|
||||
// println!("Blocking client, since it sent a blocking message");
|
||||
ss.switch_to(server_pid, None)?;
|
||||
ss.set_context_result(
|
||||
server_pid,
|
||||
ctx_number,
|
||||
xous::Result::Message(envelope),
|
||||
).and_then(|_| ss.switch_from(pid, context_nr, false))
|
||||
)
|
||||
.and_then(|_| {
|
||||
println!("464: Switching from {}", pid);
|
||||
ss.switch_from(pid, context_nr, false)
|
||||
})
|
||||
.map(|_| xous::Result::BlockedProcess)
|
||||
} else if cfg!(baremetal) {
|
||||
// println!("Setting the return value of the Server and returning to Client");
|
||||
|
|
@ -471,6 +481,9 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
.map(|_| xous::Result::Ok)
|
||||
} else {
|
||||
// println!("Setting the return value of the Server and returning to Client");
|
||||
// "Switch to" the server PID when not running on bare metal. This ensures
|
||||
// that it's "Running".
|
||||
ss.switch_to(server_pid, None)?;
|
||||
ss.set_context_result(
|
||||
server_pid,
|
||||
ctx_number,
|
||||
|
|
@ -479,10 +492,10 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
.map(|_| xous::Result::Ok)
|
||||
}
|
||||
} else {
|
||||
println!("No contexts available to handle this. Queueing message.");
|
||||
// println!("No contexts available to handle this. Queueing message.");
|
||||
// There is no server context we can use, so add the message to
|
||||
// the queue.
|
||||
let context_nr = ss.current_context_nr();
|
||||
let context_nr = ss.current_context_nr(pid);
|
||||
|
||||
// Add this message to the queue. If the queue is full, this
|
||||
// returns an error.
|
||||
|
|
@ -490,7 +503,10 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
|
||||
// Park this context if it's blocking. This is roughly
|
||||
// equivalent to a "Yield".
|
||||
if blocking {
|
||||
if !cfg!(baremetal) {
|
||||
ss.switch_from(pid, context_nr, false)?;
|
||||
Ok(xous::Result::BlockedProcess)
|
||||
} else if blocking {
|
||||
// println!("Returning to parent");
|
||||
let process = ss.get_process(pid).expect("Can't get current process");
|
||||
let ppid = process.ppid;
|
||||
|
|
@ -506,7 +522,8 @@ pub fn handle(pid: PID, call: SysCall) -> core::result::Result<xous::Result, xou
|
|||
})
|
||||
}
|
||||
SysCall::TerminateProcess => SystemServices::with_mut(|ss| {
|
||||
let context_nr = ss.current_context_nr();
|
||||
let context_nr = ss.current_context_nr(pid);
|
||||
println!("515: Switching from {}", pid);
|
||||
ss.switch_from(pid, context_nr, false)?;
|
||||
let ppid = ss.terminate_process(pid)?;
|
||||
if cfg!(baremetal) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ use xous::{rsyscall, SysCall};
|
|||
|
||||
mod shutdown;
|
||||
|
||||
const SERVER_SPEC: &str = "localhost:0";
|
||||
|
||||
fn start_kernel(server_spec: &str) -> (JoinHandle<()>, SocketAddr) {
|
||||
let server_addr = server_spec
|
||||
.to_socket_addrs()
|
||||
|
|
@ -46,10 +48,8 @@ fn start_kernel(server_spec: &str) -> (JoinHandle<()>, SocketAddr) {
|
|||
|
||||
#[test]
|
||||
fn shutdown() {
|
||||
let server_spec = "localhost:0";
|
||||
|
||||
// Start the server in another thread.
|
||||
let (main_thread, server_spec) = start_kernel(server_spec);
|
||||
let (main_thread, server_spec) = start_kernel(SERVER_SPEC);
|
||||
|
||||
// This is now the client.
|
||||
xous::hosted::set_xous_address(server_spec);
|
||||
|
|
@ -64,9 +64,8 @@ fn shutdown() {
|
|||
|
||||
#[test]
|
||||
fn send_scalar_message() {
|
||||
let server_spec = "localhost:0";
|
||||
// Start the server in another thread
|
||||
let (main_thread, server_spec) = start_kernel(server_spec);
|
||||
let (main_thread, server_spec) = start_kernel(SERVER_SPEC);
|
||||
|
||||
xous::hosted::set_xous_address(server_spec);
|
||||
|
||||
|
|
@ -123,11 +122,10 @@ fn send_scalar_message() {
|
|||
|
||||
#[test]
|
||||
fn send_move_message() {
|
||||
let server_spec = "localhost:0";
|
||||
let test_str = "Hello, world!";
|
||||
let test_bytes = test_str.as_bytes();
|
||||
|
||||
let (main_thread, server_spec) = start_kernel(server_spec);
|
||||
let (main_thread, server_spec) = start_kernel(SERVER_SPEC);
|
||||
|
||||
let (server_addr_send, server_addr_recv) = channel();
|
||||
|
||||
|
|
@ -175,18 +173,19 @@ fn send_move_message() {
|
|||
|
||||
#[test]
|
||||
fn send_borrow_message() {
|
||||
let server_spec = "localhost:0";
|
||||
let (main_thread, server_spec) = start_kernel(server_spec);
|
||||
let (main_thread, server_spec) = start_kernel(SERVER_SPEC);
|
||||
let (server_addr_send, server_addr_recv) = channel();
|
||||
let test_str = "Hello, world!";
|
||||
let test_bytes = test_str.as_bytes();
|
||||
|
||||
let xous_server = spawn(move || {
|
||||
xous::hosted::set_xous_address(server_spec);
|
||||
println!("SERVER: Creating server...");
|
||||
let sid = xous::create_server(0x7884_3123).expect("couldn't create test server");
|
||||
server_addr_send.send(sid).unwrap();
|
||||
println!("SERVER: Receiving message...");
|
||||
let envelope = xous::receive_message(sid).expect("couldn't receive messages");
|
||||
// println!("Received message from {}", envelope.sender);
|
||||
println!("SERVER: Received message from {}", envelope.sender);
|
||||
let message = envelope.message;
|
||||
if let xous::Message::Borrow(m) = message {
|
||||
let buf = m.buf;
|
||||
|
|
@ -194,9 +193,10 @@ fn send_borrow_message() {
|
|||
Box::from_raw(core::slice::from_raw_parts_mut(buf.as_mut_ptr(), buf.len()))
|
||||
};
|
||||
assert_eq!(*test_bytes, *bt);
|
||||
// let s = String::from_utf8_lossy(&bt);
|
||||
// println!("Got message: {:?} -> \"{}\"", bt, s);
|
||||
let s = String::from_utf8_lossy(&bt);
|
||||
println!("SERVER: Got message: {:?} -> \"{}\"", bt, s);
|
||||
xous::return_memory(envelope.sender, m.buf).unwrap();
|
||||
println!("SERVER: Returned memory");
|
||||
} else {
|
||||
panic!("unexpected message type");
|
||||
}
|
||||
|
|
@ -206,16 +206,22 @@ fn send_borrow_message() {
|
|||
xous::hosted::set_xous_address(server_spec);
|
||||
|
||||
// Get the server address (out of band) so we know what to connect to
|
||||
println!("CLIENT: Waiting for server to start...");
|
||||
let sid = server_addr_recv.recv().unwrap();
|
||||
|
||||
// Perform a connection to the server
|
||||
println!("CLIENT: Connecting to server...");
|
||||
let conn = xous::connect(sid).expect("couldn't connect to server");
|
||||
|
||||
// Convert the message into a "Carton" that can be shipped as a message
|
||||
println!("CLIENT: Creating carton...");
|
||||
let carton = xous::carton::Carton::from_bytes(test_bytes);
|
||||
|
||||
// Send the message to the server
|
||||
println!("CLIENT: Lending message...");
|
||||
carton.lend(conn, 0).expect("couldn't lend message to server");
|
||||
|
||||
println!("CLIENT: Done");
|
||||
});
|
||||
|
||||
xous_server.join().expect("couldn't join server process");
|
||||
|
|
@ -229,8 +235,7 @@ fn send_borrow_message() {
|
|||
|
||||
#[test]
|
||||
fn send_mutableborrow_message() {
|
||||
let server_spec = "localhost:0";
|
||||
let (main_thread, server_spec) = start_kernel(server_spec);
|
||||
let (main_thread, server_spec) = start_kernel(SERVER_SPEC);
|
||||
let (server_addr_send, server_addr_recv) = channel();
|
||||
let test_str = "Hello, world!";
|
||||
let test_bytes = test_str.as_bytes();
|
||||
|
|
@ -287,3 +292,83 @@ fn send_mutableborrow_message() {
|
|||
|
||||
main_thread.join().expect("couldn't join kernel process");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_mutableborrow_message_long() {
|
||||
let (main_thread, server_spec) = start_kernel(SERVER_SPEC);
|
||||
let (server_addr_send, server_addr_recv) = channel();
|
||||
let test_str = "Hello, world!";
|
||||
let test_bytes = test_str.as_bytes();
|
||||
|
||||
let loops = 50;
|
||||
|
||||
let xous_server = spawn(move || {
|
||||
xous::hosted::set_xous_address(server_spec);
|
||||
let sid = xous::create_server(0x7884_3123).expect("couldn't create test server");
|
||||
server_addr_send.send(sid).unwrap();
|
||||
|
||||
for iteration in 0..loops {
|
||||
let envelope = xous::receive_message(sid).expect("couldn't receive messages");
|
||||
let message = envelope.message;
|
||||
if let xous::Message::MutableBorrow(m) = message {
|
||||
let buf = m.buf;
|
||||
let mut bt = unsafe {
|
||||
Box::from_raw(core::slice::from_raw_parts_mut(buf.as_mut_ptr(), buf.len()))
|
||||
};
|
||||
for letter in bt.iter_mut() {
|
||||
*letter = (*letter).wrapping_add((iteration & 0xff) as u8);
|
||||
}
|
||||
xous::return_memory(envelope.sender, m.buf).unwrap();
|
||||
} else {
|
||||
panic!("unexpected message type");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let xous_client = spawn(move || {
|
||||
xous::hosted::set_xous_address(server_spec);
|
||||
|
||||
// Get the server address (out of band) so we know what to connect to
|
||||
let sid = server_addr_recv.recv().unwrap();
|
||||
|
||||
// Perform a connection to the server
|
||||
let conn = xous::connect(sid).expect("couldn't connect to server");
|
||||
|
||||
// Convert the message into a "Carton" that can be shipped as a message
|
||||
for iteration in 0..loops {
|
||||
let mut carton = xous::carton::Carton::from_bytes(&test_bytes);
|
||||
let mut check_bytes = test_bytes.to_vec();
|
||||
for letter in check_bytes.iter_mut() {
|
||||
*letter = (*letter).wrapping_add((iteration & 0xff) as u8);
|
||||
}
|
||||
|
||||
// Send the message to the server
|
||||
carton.lend_mut(conn, 3).expect("couldn't mutably lend data");
|
||||
|
||||
let modified_bytes: &[u8] = carton.as_ref();
|
||||
assert_eq!(&check_bytes, &modified_bytes);
|
||||
}
|
||||
});
|
||||
|
||||
xous_server.join().expect("couldn't join server process");
|
||||
xous_client.join().expect("couldn't join client process");
|
||||
|
||||
// Any process ought to be able to shut down the system currently.
|
||||
rsyscall(SysCall::Shutdown).expect("unable to shutdown server");
|
||||
|
||||
main_thread.join().expect("couldn't join kernel process");
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn multiple_contexts() {
|
||||
// // Start the kernel in its own thread
|
||||
// let (main_thread, server_spec) = start_kernel(SERVER_SPEC);
|
||||
|
||||
// let (server_addr_send, server_addr_recv) = channel();
|
||||
// xous::create_server(name)
|
||||
|
||||
// // Any process ought to be able to shut down the system currently.
|
||||
// rsyscall(SysCall::Shutdown).expect("unable to shutdown server");
|
||||
|
||||
// main_thread.join().expect("couldn't join kernel process");
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -607,7 +607,9 @@ impl SysCall {
|
|||
),
|
||||
_ => SysCall::Invalid(a1, a2, a3, a4, a5, a6, a7),
|
||||
},
|
||||
Some(SysCallNumber::ReturnMemory) => SysCall::ReturnMemory(a1, MemoryRange::new(a2, a3)),
|
||||
Some(SysCallNumber::ReturnMemory) => {
|
||||
SysCall::ReturnMemory(a1, MemoryRange::new(a2, a3))
|
||||
}
|
||||
Some(SysCallNumber::SpawnThread) => SysCall::SpawnThread(
|
||||
MemoryAddress::new(a1).ok_or(Error::InvalidSyscall)?,
|
||||
MemoryAddress::new(a2).ok_or(Error::InvalidSyscall)?,
|
||||
|
|
@ -798,6 +800,16 @@ pub fn wait_event() {
|
|||
rsyscall(SysCall::WaitEvent).expect("wait_event returned an error");
|
||||
}
|
||||
|
||||
/// Create a new thread
|
||||
// pub fn spawn<F, T>(f: F) -> JoinHandle<T>
|
||||
// where
|
||||
// F: FnOnce() -> T,
|
||||
// F: Send + 'static,
|
||||
// T: Send + 'static,
|
||||
// {
|
||||
// Builder::new().spawn(f).expect("failed to spawn thread")
|
||||
// }
|
||||
|
||||
pub fn rsyscall(call: SysCall) -> SysCallResult {
|
||||
let mut ret = Result::Ok;
|
||||
let args = call.as_args();
|
||||
|
|
|
|||
Loading…
Reference in a new issue