2020-07-26 02:54:54 +00:00
pub use crate ::arch ::process ::Thread ;
2020-06-15 10:13:10 +00:00
use core ::mem ;
2020-12-04 14:16:24 +00:00
use xous_kernel ::{ MemoryAddress , MemoryRange , MemorySize , Message , MessageSender , PID , SID , TID } ;
2020-04-01 09:27:59 +00:00
pub struct SenderID {
2020-10-29 11:46:17 +00:00
/// The index of the server within the SystemServices table
pub sidx : usize ,
2020-09-23 02:52:22 +00:00
/// The index into the queue array
pub idx : usize ,
2020-12-04 14:38:35 +00:00
/// The process ID that sent this message
pid : Option < PID > ,
}
impl SenderID {
pub fn new ( sidx : usize , idx : usize , pid : Option < PID > ) -> Self {
SenderID { sidx , idx , pid }
}
2020-04-01 09:27:59 +00:00
}
2020-09-23 02:52:22 +00:00
impl From < usize > for SenderID {
fn from ( item : usize ) -> SenderID {
SenderID {
2020-12-04 14:38:35 +00:00
sidx : ( item > > 16 ) & 0xff ,
2020-09-23 02:52:22 +00:00
idx : item & 0xffff ,
2020-12-04 14:38:35 +00:00
pid : PID ::new ( ( item > > 24 ) as u8 ) ,
2020-09-23 02:52:22 +00:00
}
}
}
impl Into < usize > for SenderID {
fn into ( self ) -> usize {
2020-12-04 14:38:35 +00:00
( self . pid . map ( | x | x . get ( ) as usize ) . unwrap_or ( 0 ) < < 24 )
| ( ( self . sidx < < 16 ) & 0x00ff0000 )
| ( self . idx & 0xffff )
2020-04-01 09:27:59 +00:00
}
}
2020-03-24 06:13:11 +00:00
2020-12-04 14:16:24 +00:00
impl From < MessageSender > for SenderID {
fn from ( item : MessageSender ) -> SenderID {
SenderID ::from ( item . to_usize ( ) )
}
}
impl Into < MessageSender > for SenderID {
fn into ( self ) -> MessageSender {
MessageSender ::from_usize ( self . into ( ) )
}
}
2020-10-29 11:46:17 +00:00
#[ derive(Debug) ]
2020-04-03 04:28:44 +00:00
pub enum WaitingMessage {
2020-06-22 09:42:24 +00:00
/// There is no waiting message.
2020-04-03 04:28:44 +00:00
None ,
2020-06-22 09:42:24 +00:00
/// The memory was borrowed and should be returned to the given process.
2020-07-21 01:44:16 +00:00
BorrowedMemory ( PID , TID , MemoryAddress , MemoryAddress , MemorySize ) ,
2020-06-22 09:42:24 +00:00
/// The memory was moved, and so shouldn't be returned.
2020-04-03 04:28:44 +00:00
MovedMemory ,
2020-06-22 09:42:24 +00:00
2020-09-23 02:52:22 +00:00
/// The message was a scalar message, so you should return the result to the process
ScalarMessage ( PID , TID ) ,
2020-06-22 09:42:24 +00:00
/// This memory should be returned to the system.
ForgetMemory ( MemoryRange ) ,
2020-04-03 04:28:44 +00:00
}
2020-03-30 04:35:50 +00:00
/// Internal representation of a queued message for a server. This should be
/// exactly 8 words / 32 bytes, yielding 128 queued messages per server
2020-03-24 06:13:11 +00:00
#[ repr(usize) ]
2020-04-01 09:27:59 +00:00
#[ derive(PartialEq, Debug) ]
2020-03-24 06:13:11 +00:00
enum QueuedMessage {
Empty ,
2020-09-22 14:05:18 +00:00
BlockingScalarMessage (
2020-09-23 02:52:22 +00:00
u16 , /* client PID */
2020-11-11 08:04:35 +00:00
u16 , /* client TID */
2020-09-23 02:52:22 +00:00
usize , /* server return address */
2020-09-22 14:05:18 +00:00
usize , /* id */
usize , /* arg1 */
usize , /* arg2 */
usize , /* arg3 */
usize , /* arg4 */
) ,
2020-03-24 06:13:11 +00:00
ScalarMessage (
2020-09-23 02:52:22 +00:00
u16 , /* client PID */
2020-11-11 08:04:35 +00:00
u16 , /* client TID */
2020-09-23 02:52:22 +00:00
usize , /* server return address */
2020-03-24 06:13:11 +00:00
usize , /* id */
usize , /* arg1 */
usize , /* arg2 */
usize , /* arg3 */
usize , /* arg4 */
) ,
MemoryMessageSend (
2020-09-23 02:52:22 +00:00
u16 , /* client PID */
2020-11-11 08:04:35 +00:00
u16 , /* client TID */
2020-04-01 09:27:59 +00:00
usize , /* reserved */
2020-03-24 06:13:11 +00:00
usize , /* id */
usize , /* buf */
usize , /* buf_size */
usize , /* offset */
usize , /* valid */
) ,
MemoryMessageROLend (
2020-09-23 02:52:22 +00:00
u16 , /* client PID */
2020-11-11 08:04:35 +00:00
u16 , /* client TID */
2020-09-23 02:52:22 +00:00
usize , /* address of memory base in server */
2020-03-24 06:13:11 +00:00
usize , /* id */
usize , /* buf */
usize , /* buf_size */
usize , /* offset */
usize , /* valid */
) ,
MemoryMessageRWLend (
2020-09-23 02:52:22 +00:00
u16 , /* client PID */
2020-11-11 08:04:35 +00:00
u16 , /* client TID */
2020-09-23 02:52:22 +00:00
usize , /* address of memory base in server */
2020-03-24 06:13:11 +00:00
usize , /* id */
usize , /* buf */
usize , /* buf_size */
usize , /* offset */
usize , /* valid */
) ,
2020-04-01 09:27:59 +00:00
2020-06-22 09:42:24 +00:00
/// The process lending this memory terminated before
/// we could receive the message.
MemoryMessageROLendTerminated (
2020-09-23 02:52:22 +00:00
u16 , /* client PID */
2020-11-11 08:04:35 +00:00
u16 , /* client TID */
2020-09-23 02:52:22 +00:00
usize , /* address of memory base in server */
2020-06-22 09:42:24 +00:00
usize , /* id */
usize , /* buf */
usize , /* buf_size */
usize , /* offset */
usize , /* valid */
) ,
/// The process lending this memory terminated before
/// we could receive the message.
MemoryMessageRWLendTerminated (
2020-09-23 02:52:22 +00:00
u16 , /* client PID */
2020-11-11 08:04:35 +00:00
u16 , /* client TID */
2020-09-23 02:52:22 +00:00
usize , /* address of memory base in server */
2020-06-22 09:42:24 +00:00
usize , /* id */
usize , /* buf */
usize , /* buf_size */
usize , /* offset */
usize , /* valid */
) ,
2020-09-22 14:05:18 +00:00
/// The process waiting for the response terminated before
/// we could receive the message.
BlockingScalarTerminated (
2020-09-23 02:52:22 +00:00
u16 , /* client PID */
2020-11-11 08:04:35 +00:00
u16 , /* client TID */
2020-09-23 02:52:22 +00:00
usize , /* server return address */
2020-09-22 14:05:18 +00:00
usize , /* id */
usize , /* arg1 */
usize , /* arg2 */
usize , /* arg3 */
usize , /* arg4 */
) ,
2020-04-01 09:27:59 +00:00
/// When a message is taken that needs to be returned -- such as an ROLend
2020-09-23 02:52:22 +00:00
/// or RWLend -- the slot is replaced with a WaitingReturnMemory token and its
2020-04-01 09:27:59 +00:00
/// index is returned as the message sender. This is used to unblock the
/// sending process.
2020-09-23 02:52:22 +00:00
WaitingReturnMemory (
u16 , /* client PID */
2020-11-11 08:04:35 +00:00
u16 , /* client TID */
2020-09-23 02:52:22 +00:00
usize , /* address of memory base in server */
usize , /* client base address */
2020-04-01 09:27:59 +00:00
usize , /* Range size */
) ,
2020-06-22 09:42:24 +00:00
/// When a server goes away, its memory must be forgotten instead of being returned
/// to the previous process.
WaitingForget (
2020-09-23 02:52:22 +00:00
u16 , /* client PID */
2020-11-11 08:04:35 +00:00
u16 , /* client TID */
2020-09-23 02:52:22 +00:00
usize , /* address of memory base in server */
usize , /* client base address */
2020-06-22 09:42:24 +00:00
usize , /* Range size */
) ,
2020-09-22 14:05:18 +00:00
/// This is the state when a message is blocking, but has no associated memory
/// page.
2020-09-23 02:52:22 +00:00
WaitingReturnScalar (
u16 , /* client PID */
2020-11-11 08:04:35 +00:00
u16 , /* client TID */
2020-09-23 02:52:22 +00:00
usize , /* server return address */
) ,
2020-03-24 06:13:11 +00:00
}
/// A pointer to resolve a server ID to a particular process
2020-06-24 09:51:31 +00:00
#[ derive(PartialEq, Debug) ]
2020-03-24 06:13:11 +00:00
pub struct Server {
/// A randomly-generated ID
pub sid : SID ,
/// The process that owns this server
pub pid : PID ,
/// An index into the queue
queue_head : usize ,
queue_tail : usize ,
/// Where data will appear
2020-08-09 08:48:58 +00:00
#[ cfg(baremetal) ]
queue : & 'static mut [ QueuedMessage ] ,
#[ cfg(not(baremetal)) ]
2020-06-15 10:13:10 +00:00
queue : Vec < QueuedMessage > ,
2020-03-24 06:13:11 +00:00
2020-03-27 04:30:29 +00:00
/// The `context mask` is a bitfield of contexts that are able to handle
/// this message. If there are no available contexts, then messages will
2020-03-24 06:13:11 +00:00
/// need to be queued.
2020-07-21 02:01:57 +00:00
ready_threads : usize ,
2020-03-24 06:13:11 +00:00
}
impl Server {
2020-06-15 10:13:10 +00:00
/// Initialize a server in the given option array. This function is
/// designed to be called with `new` pointing to an entry in a vec.
///
/// # Errors
///
/// * **MemoryInUse**: The provided Server option already exists
2020-03-24 06:13:11 +00:00
pub fn init (
new : & mut Option < Server > ,
pid : PID ,
sid : SID ,
2020-08-09 11:02:05 +00:00
_backing : MemoryRange ,
2020-08-17 10:37:40 +00:00
) -> Result < ( ) , xous_kernel ::Error > {
2020-03-24 06:13:11 +00:00
if new ! = & None {
2020-08-17 10:37:40 +00:00
return Err ( xous_kernel ::Error ::MemoryInUse ) ;
2020-03-24 06:13:11 +00:00
}
2020-08-09 08:48:58 +00:00
#[ cfg(baremetal) ]
2020-08-09 13:52:28 +00:00
let queue = unsafe {
2020-08-09 08:48:58 +00:00
core ::slice ::from_raw_parts_mut (
2020-08-09 11:02:05 +00:00
_backing . as_mut_ptr ( ) as * mut QueuedMessage ,
_backing . len ( ) / mem ::size_of ::< QueuedMessage > ( ) ,
2020-08-09 08:48:58 +00:00
)
} ;
#[ cfg(not(baremetal)) ]
let queue = {
let mut queue = vec! [ ] ;
// TODO: Replace this with a direct operation on a passed-in page
queue . resize_with (
crate ::arch ::mem ::PAGE_SIZE / mem ::size_of ::< QueuedMessage > ( ) ,
| | QueuedMessage ::Empty ,
) ;
queue
} ;
2020-03-24 06:13:11 +00:00
* new = Some ( Server {
sid ,
pid ,
queue_head : 0 ,
queue_tail : 0 ,
queue ,
2020-07-21 02:01:57 +00:00
ready_threads : 0 ,
2020-03-24 06:13:11 +00:00
} ) ;
Ok ( ( ) )
}
2020-04-01 09:27:59 +00:00
2020-06-25 09:41:17 +00:00
/// Take a current slot and replace it with `None`, clearing out the contents of the queue.
2020-08-17 10:37:40 +00:00
pub fn destroy ( current : & mut Option < Server > ) -> Result < ( ) , xous_kernel ::Error > {
2020-07-26 02:54:54 +00:00
if let Some ( mut server ) = current . take ( ) {
server . queue_head = 0 ;
server . queue_tail = 0 ;
server . ready_threads = 0 ;
}
2020-06-25 09:41:17 +00:00
Ok ( ( ) )
}
2020-06-03 10:28:22 +00:00
// pub fn print_queue(&self) {
// println!(" Q Queue Head: {}", self.queue_head);
// println!(" Q Queue Tail: {}", self.queue_tail);
// for (_idx, _entry) in self.queue.iter().enumerate() {
// if _entry != &QueuedMessage::Empty {
// println!(" Q entry[{}]: {:?}", _idx, _entry);
// }
// }
// }
2020-04-01 09:27:59 +00:00
2020-06-22 09:42:24 +00:00
/// When a process terminates, there may be memory that is lent to us.
/// Mark all of that memory to be discarded when it is returned, rather than
/// giving it back to the previous process space.
pub fn discard_messages_for_pid ( & mut self , pid : PID ) {
for entry in self . queue . iter_mut ( ) {
2020-07-29 14:48:48 +00:00
match * entry {
QueuedMessage ::MemoryMessageROLend (
2020-07-15 08:09:42 +00:00
msg_pid ,
2020-11-11 08:04:35 +00:00
tid ,
2020-07-15 08:09:42 +00:00
arg1 ,
arg2 ,
arg3 ,
arg4 ,
arg5 ,
arg6 ,
) = > {
if msg_pid = = pid . get ( ) as _ {
* entry = QueuedMessage ::MemoryMessageROLendTerminated (
2020-11-11 08:04:35 +00:00
msg_pid , tid , arg1 , arg2 , arg3 , arg4 , arg5 , arg6 ,
2020-07-15 08:09:42 +00:00
) ;
2020-06-25 09:41:17 +00:00
}
2020-06-22 09:42:24 +00:00
}
2020-07-29 14:48:48 +00:00
QueuedMessage ::MemoryMessageRWLend (
2020-07-15 08:09:42 +00:00
msg_pid ,
2020-11-11 08:04:35 +00:00
tid ,
2020-07-15 08:09:42 +00:00
arg1 ,
arg2 ,
arg3 ,
arg4 ,
arg5 ,
arg6 ,
) = > {
if msg_pid = = pid . get ( ) as _ {
* entry = QueuedMessage ::MemoryMessageRWLendTerminated (
2020-11-11 08:04:35 +00:00
msg_pid , tid , arg1 , arg2 , arg3 , arg4 , arg5 , arg6 ,
2020-07-15 08:09:42 +00:00
) ;
2020-06-25 09:41:17 +00:00
}
2020-06-22 09:42:24 +00:00
}
2020-09-22 14:05:18 +00:00
QueuedMessage ::BlockingScalarMessage (
msg_pid ,
2020-11-11 08:04:35 +00:00
tid ,
2020-09-22 14:05:18 +00:00
arg1 ,
arg2 ,
arg3 ,
arg4 ,
arg5 ,
arg6 ,
) = > {
if msg_pid = = pid . get ( ) as _ {
* entry = QueuedMessage ::BlockingScalarTerminated (
2020-11-11 08:04:35 +00:00
msg_pid , tid , arg1 , arg2 , arg3 , arg4 , arg5 , arg6 ,
2020-09-22 14:05:18 +00:00
) ;
}
}
2020-07-04 03:58:18 +00:00
// For "Scalar" and "Move" messages, this memory has already
// been moved into this process, so memory will be reclaimed
// when the process terminates.
_ = > ( ) ,
2020-06-22 09:42:24 +00:00
}
}
}
2020-09-23 02:52:22 +00:00
/// Convert a `QueuedMesage::WaitingReturnMemory` into `QueuedMessage::Empty`
2020-04-01 09:27:59 +00:00
/// 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.
2020-07-15 08:09:42 +00:00
pub fn take_waiting_message (
& mut self ,
idx : usize ,
2020-09-23 02:52:22 +00:00
buf : Option < & MemoryRange > ,
2020-08-17 10:37:40 +00:00
) -> Result < WaitingMessage , xous_kernel ::Error > {
2020-12-04 12:30:00 +00:00
let current_val = self
. queue
. get_mut ( idx )
. ok_or ( xous_kernel ::Error ::BadAddress ) ? ;
2020-12-14 09:02:58 +00:00
klog! ( " memory in queue[{}]: {:?} " , idx , current_val ) ;
2020-12-01 05:27:30 +00:00
let ( pid , tid , server_addr , client_addr , len , forget , is_memory ) = match * current_val {
2020-11-11 08:04:35 +00:00
QueuedMessage ::WaitingReturnMemory ( pid , tid , server_addr , client_addr , len ) = > {
( pid , tid , server_addr , client_addr , len , false , true )
2020-06-22 09:42:24 +00:00
}
2020-11-11 08:04:35 +00:00
QueuedMessage ::WaitingForget ( pid , tid , server_addr , client_addr , len ) = > {
( pid , tid , server_addr , client_addr , len , true , true )
2020-09-23 02:52:22 +00:00
}
2020-11-11 08:04:35 +00:00
QueuedMessage ::WaitingReturnScalar ( pid , tid , return_address ) = > {
( pid , tid , return_address , 0 , 0 , true , false )
2020-04-01 09:27:59 +00:00
}
2020-04-03 04:28:44 +00:00
_ = > return Ok ( WaitingMessage ::None ) ,
2020-04-01 09:27:59 +00:00
} ;
2020-09-23 02:52:22 +00:00
// Sanity check the specified address was correct, and matches what we
// had cached.
2020-10-29 11:46:17 +00:00
if is_memory & & cfg! ( baremetal ) {
2020-09-23 02:52:22 +00:00
let buf = buf . expect ( " memory message expected but no buffer passed! " ) ;
if server_addr ! = buf . as_ptr ( ) as usize | | len ! = buf . len ( ) {
2020-10-29 11:46:17 +00:00
// println!("KERNEL: Memory is attached but the returned buffer doesn't match (len: {} vs {}), buf addr: {:08x} vs {:08x}", len, buf.len(), server_addr, buf.as_ptr() as usize);
2020-12-01 05:27:30 +00:00
Err ( xous_kernel ::Error ::BadAddress ) ? ;
2020-09-23 02:52:22 +00:00
}
2020-07-14 04:11:57 +00:00
}
2020-12-01 05:27:30 +00:00
* current_val = QueuedMessage ::Empty ;
2020-04-01 09:27:59 +00:00
self . queue_tail + = 1 ;
if self . queue_tail > = self . queue . len ( ) {
self . queue_tail = 0 ;
}
2020-11-11 08:04:35 +00:00
// Destructure the PID and context ID from the `pid_tid` field
2020-12-01 03:53:50 +00:00
klog! (
" taking waiting message and returning to pid: {} tid: {} " ,
pid ,
tid
) ;
2020-06-22 09:42:24 +00:00
2020-09-23 02:52:22 +00:00
if ! is_memory {
return Ok ( WaitingMessage ::ScalarMessage (
PID ::new ( pid as _ ) . unwrap ( ) ,
2020-11-11 08:04:35 +00:00
tid as _ ,
2020-09-23 02:52:22 +00:00
) ) ;
}
2020-06-22 09:42:24 +00:00
if forget {
2020-07-15 08:09:42 +00:00
return Ok ( WaitingMessage ::ForgetMemory ( MemoryRange ::new (
server_addr ,
len ,
2020-08-03 09:40:57 +00:00
) ? ) ) ;
2020-06-22 09:42:24 +00:00
}
// If a `move` address somehow ends up here, indicate the memory has been moved.
2020-04-01 09:27:59 +00:00
let server_addr = match MemoryAddress ::new ( server_addr ) {
Some ( o ) = > o ,
2020-04-03 04:28:44 +00:00
None = > return Ok ( WaitingMessage ::MovedMemory ) ,
2020-04-01 09:27:59 +00:00
} ;
2020-06-22 09:42:24 +00:00
2020-04-03 04:28:44 +00:00
let client_addr = MemoryAddress ::new ( client_addr )
. expect ( " client memory address was 0, but server address was not " ) ;
2020-04-01 09:27:59 +00:00
let len = MemorySize ::new ( len ) . expect ( " memory length was 0, but address was not None " ) ;
2020-04-03 04:28:44 +00:00
Ok ( WaitingMessage ::BorrowedMemory (
2020-07-15 08:09:42 +00:00
PID ::new ( pid as _ ) . unwrap ( ) ,
2020-11-11 08:04:35 +00:00
tid as _ ,
2020-04-03 04:28:44 +00:00
server_addr ,
client_addr ,
len ,
) )
2020-04-01 09:27:59 +00:00
}
2020-09-23 02:52:22 +00:00
/// Remove a message from the server's queue and replace it with either a QueuedMessage::WaitingReturnMemory
2020-06-16 08:34:49 +00:00
/// or, for Scalar messages, QueuedMessage::Empty.
///
/// For non-Scalar messages, you must call `take_waiting_message()` in order to return
/// memory to the calling process.
///
/// # Returns
///
/// * **None**: There are no waiting messages
/// ***Some(MessageEnvelope): This message is queued.
2020-10-29 11:46:17 +00:00
pub fn take_next_message ( & mut self , sidx : usize ) -> Option < xous_kernel ::MessageEnvelope > {
2020-07-14 02:08:49 +00:00
// println!(
2020-09-23 02:52:22 +00:00
// "queue_head: ((({}))) queue_tail: ((({}))): {:?} CID: ((({})))",
2020-12-01 05:20:34 +00:00
// self.queue_head, self.queue_tail, self.queue[self.queue_tail], sidx
2020-07-14 02:08:49 +00:00
// );
2020-12-04 14:38:35 +00:00
use core ::convert ::TryInto ;
let mut sender = SenderID ::new ( sidx , self . queue_tail , None ) ;
2020-09-22 14:05:18 +00:00
let ( result , response ) = match self . queue [ self . queue_tail ] {
2020-03-24 06:13:11 +00:00
QueuedMessage ::Empty = > return None ,
2020-09-23 02:52:22 +00:00
QueuedMessage ::WaitingReturnMemory ( _ , _ , _ , _ , _ ) = > return None ,
2020-07-15 08:09:42 +00:00
QueuedMessage ::WaitingForget ( _ , _ , _ , _ , _ ) = > return None ,
2020-09-23 02:52:22 +00:00
QueuedMessage ::WaitingReturnScalar ( _ , _ , _ ) = > return None ,
2020-03-24 06:13:11 +00:00
QueuedMessage ::MemoryMessageROLend (
2020-07-15 08:09:42 +00:00
pid ,
2020-11-11 08:04:35 +00:00
tid ,
2020-04-01 09:27:59 +00:00
client_addr ,
2020-03-24 06:13:11 +00:00
id ,
buf ,
buf_size ,
offset ,
valid ,
2020-12-04 14:38:35 +00:00
) = > {
sender . pid = PID ::new ( pid . try_into ( ) . unwrap ( ) ) ;
(
xous_kernel ::MessageEnvelope {
sender : sender . into ( ) ,
body : xous_kernel ::Message ::Borrow ( xous_kernel ::MemoryMessage {
id ,
buf : MemoryRange ::new ( buf , buf_size ) . ok ( ) ? ,
offset : MemorySize ::new ( offset ) ,
valid : MemorySize ::new ( valid ) ,
} ) ,
} ,
QueuedMessage ::WaitingReturnMemory ( pid , tid , buf , client_addr , buf_size ) ,
)
}
2020-03-24 06:13:11 +00:00
QueuedMessage ::MemoryMessageRWLend (
2020-07-15 08:09:42 +00:00
pid ,
2020-11-11 08:04:35 +00:00
tid ,
2020-04-01 09:27:59 +00:00
client_addr ,
2020-03-24 06:13:11 +00:00
id ,
buf ,
buf_size ,
offset ,
valid ,
2020-12-04 14:38:35 +00:00
) = > {
sender . pid = PID ::new ( pid . try_into ( ) . unwrap ( ) ) ;
(
xous_kernel ::MessageEnvelope {
sender : sender . into ( ) ,
body : xous_kernel ::Message ::MutableBorrow ( xous_kernel ::MemoryMessage {
id ,
buf : MemoryRange ::new ( buf , buf_size ) . ok ( ) ? ,
offset : MemorySize ::new ( offset ) ,
valid : MemorySize ::new ( valid ) ,
} ) ,
} ,
QueuedMessage ::WaitingReturnMemory ( pid , tid , buf , client_addr , buf_size ) ,
)
}
2020-06-22 09:42:24 +00:00
QueuedMessage ::MemoryMessageROLendTerminated (
2020-07-15 08:09:42 +00:00
pid ,
2020-11-11 08:04:35 +00:00
tid ,
2020-06-22 09:42:24 +00:00
client_addr ,
id ,
buf ,
buf_size ,
offset ,
valid ,
2020-12-04 14:38:35 +00:00
) = > {
sender . pid = PID ::new ( pid . try_into ( ) . unwrap ( ) ) ;
(
xous_kernel ::MessageEnvelope {
sender : sender . into ( ) ,
body : xous_kernel ::Message ::Borrow ( xous_kernel ::MemoryMessage {
id ,
buf : MemoryRange ::new ( buf , buf_size ) . ok ( ) ? ,
offset : MemorySize ::new ( offset ) ,
valid : MemorySize ::new ( valid ) ,
} ) ,
} ,
QueuedMessage ::WaitingReturnMemory ( pid , tid , buf , client_addr , buf_size ) ,
)
}
2020-06-22 09:42:24 +00:00
QueuedMessage ::MemoryMessageRWLendTerminated (
2020-07-15 08:09:42 +00:00
pid ,
2020-11-11 08:04:35 +00:00
tid ,
2020-06-22 09:42:24 +00:00
client_addr ,
id ,
buf ,
buf_size ,
offset ,
valid ,
2020-12-04 14:38:35 +00:00
) = > {
sender . pid = PID ::new ( pid . try_into ( ) . unwrap ( ) ) ;
(
xous_kernel ::MessageEnvelope {
sender : sender . into ( ) ,
body : xous_kernel ::Message ::MutableBorrow ( xous_kernel ::MemoryMessage {
id ,
buf : MemoryRange ::new ( buf , buf_size ) . ok ( ) ? ,
offset : MemorySize ::new ( offset ) ,
valid : MemorySize ::new ( valid ) ,
} ) ,
} ,
QueuedMessage ::WaitingReturnMemory ( pid , tid , buf , client_addr , buf_size ) ,
)
}
2020-09-22 14:05:18 +00:00
QueuedMessage ::BlockingScalarMessage (
2020-07-15 08:09:42 +00:00
pid ,
2020-11-11 08:04:35 +00:00
tid ,
2020-09-23 02:52:22 +00:00
client_addr ,
2020-09-22 14:05:18 +00:00
id ,
arg1 ,
arg2 ,
arg3 ,
arg4 ,
2020-12-04 14:38:35 +00:00
) = > {
sender . pid = PID ::new ( pid . try_into ( ) . unwrap ( ) ) ;
(
xous_kernel ::MessageEnvelope {
sender : sender . into ( ) ,
body : xous_kernel ::Message ::BlockingScalar ( xous_kernel ::ScalarMessage {
id ,
arg1 ,
arg2 ,
arg3 ,
arg4 ,
} ) ,
} ,
QueuedMessage ::WaitingReturnScalar ( pid , tid , client_addr ) ,
)
}
2020-04-01 09:27:59 +00:00
QueuedMessage ::MemoryMessageSend (
2020-12-04 14:38:35 +00:00
pid ,
2020-11-11 08:04:35 +00:00
_tid ,
2020-04-01 09:27:59 +00:00
_reserved ,
id ,
buf ,
buf_size ,
offset ,
valid ,
2020-06-16 08:34:49 +00:00
) = > {
2020-12-04 14:38:35 +00:00
sender . pid = PID ::new ( pid . try_into ( ) . unwrap ( ) ) ;
2020-08-17 10:37:40 +00:00
let msg = xous_kernel ::MessageEnvelope {
2020-12-04 14:38:35 +00:00
sender : sender . into ( ) ,
2020-08-29 14:10:24 +00:00
body : xous_kernel ::Message ::Move ( xous_kernel ::MemoryMessage {
2020-04-01 09:27:59 +00:00
id ,
2020-08-03 09:40:57 +00:00
buf : MemoryRange ::new ( buf , buf_size ) . ok ( ) ? ,
2020-04-01 09:27:59 +00:00
offset : MemorySize ::new ( offset ) ,
valid : MemorySize ::new ( valid ) ,
} ) ,
2020-06-16 08:34:49 +00:00
} ;
self . queue [ self . queue_tail ] = QueuedMessage ::Empty ;
self . queue_tail + = 1 ;
if self . queue_tail > = self . queue . len ( ) {
self . queue_tail = 0 ;
}
return Some ( msg ) ;
}
// Scalar messages have nothing to return, so they can go straight to the `Free` state
2020-12-04 14:38:35 +00:00
QueuedMessage ::ScalarMessage ( pid , _tid , _reserved , id , arg1 , arg2 , arg3 , arg4 ) = > {
sender . pid = PID ::new ( pid . try_into ( ) . unwrap ( ) ) ;
2020-08-17 10:37:40 +00:00
let msg = xous_kernel ::MessageEnvelope {
2020-12-04 14:38:35 +00:00
sender : sender . into ( ) ,
2020-08-29 14:10:24 +00:00
body : xous_kernel ::Message ::Scalar ( xous_kernel ::ScalarMessage {
2020-03-24 06:13:11 +00:00
id ,
arg1 ,
arg2 ,
arg3 ,
arg4 ,
} ) ,
2020-06-16 08:34:49 +00:00
} ;
self . queue [ self . queue_tail ] = QueuedMessage ::Empty ;
self . queue_tail + = 1 ;
if self . queue_tail > = self . queue . len ( ) {
self . queue_tail = 0 ;
}
return Some ( msg ) ;
}
2020-09-23 02:52:22 +00:00
QueuedMessage ::BlockingScalarTerminated (
2020-12-04 14:38:35 +00:00
pid ,
2020-11-11 08:04:35 +00:00
_tid ,
2020-09-23 02:52:22 +00:00
_reserved ,
id ,
arg1 ,
arg2 ,
arg3 ,
arg4 ,
) = > {
2020-12-04 14:38:35 +00:00
sender . pid = PID ::new ( pid . try_into ( ) . unwrap ( ) ) ;
2020-09-22 14:05:18 +00:00
let msg = xous_kernel ::MessageEnvelope {
2020-12-04 14:38:35 +00:00
sender : sender . into ( ) ,
2020-09-22 14:05:18 +00:00
body : xous_kernel ::Message ::Scalar ( xous_kernel ::ScalarMessage {
id ,
arg1 ,
arg2 ,
arg3 ,
arg4 ,
} ) ,
} ;
self . queue [ self . queue_tail ] = QueuedMessage ::Empty ;
self . queue_tail + = 1 ;
if self . queue_tail > = self . queue . len ( ) {
self . queue_tail = 0 ;
}
return Some ( msg ) ;
}
2020-03-24 06:13:11 +00:00
} ;
2020-09-22 14:05:18 +00:00
self . queue [ self . queue_tail ] = response ;
Some ( result )
2020-03-24 06:13:11 +00:00
}
/// Add the given message to this server's queue.
2020-04-01 09:27:59 +00:00
///
/// # Errors
///
/// * **ServerQueueFull**: The server queue cannot accept any more messages
2020-03-24 06:13:11 +00:00
pub fn queue_message (
& mut self ,
2020-04-01 09:27:59 +00:00
pid : PID ,
2020-07-21 01:44:16 +00:00
context : TID ,
2020-08-17 10:37:40 +00:00
message : xous_kernel ::Message ,
2020-04-01 09:27:59 +00:00
original_address : Option < MemoryAddress > ,
2020-08-17 10:37:40 +00:00
) -> core ::result ::Result < usize , xous_kernel ::Error > {
2020-11-11 08:04:35 +00:00
// println!("Queueing message: {:?} for pid: {} tid: {}", message, pid.get(), context);
2020-03-24 06:13:11 +00:00
if self . queue [ self . queue_head ] ! = QueuedMessage ::Empty {
2020-08-17 10:37:40 +00:00
return Err ( xous_kernel ::Error ::ServerQueueFull ) ;
2020-03-24 06:13:11 +00:00
}
2020-04-01 09:27:59 +00:00
self . queue [ self . queue_head ] = match message {
2020-08-17 10:37:40 +00:00
xous_kernel ::Message ::Scalar ( msg ) = > QueuedMessage ::ScalarMessage (
2020-07-15 08:09:42 +00:00
pid . get ( ) as _ ,
context as _ ,
2020-04-01 09:27:59 +00:00
original_address . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) ,
2020-03-31 10:03:19 +00:00
msg . id ,
msg . arg1 ,
msg . arg2 ,
msg . arg3 ,
msg . arg4 ,
) ,
2020-09-22 14:05:18 +00:00
xous_kernel ::Message ::BlockingScalar ( msg ) = > QueuedMessage ::BlockingScalarMessage (
pid . get ( ) as _ ,
context as _ ,
original_address . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) ,
msg . id ,
msg . arg1 ,
msg . arg2 ,
msg . arg3 ,
msg . arg4 ,
) ,
2020-08-17 10:37:40 +00:00
xous_kernel ::Message ::Move ( msg ) = > QueuedMessage ::MemoryMessageSend (
2020-07-15 08:09:42 +00:00
pid . get ( ) as _ ,
context as _ ,
2020-04-01 09:27:59 +00:00
original_address . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) ,
msg . id ,
msg . buf . addr . get ( ) ,
msg . buf . size . get ( ) ,
msg . offset . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) as usize ,
msg . valid . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) as usize ,
) ,
2020-08-17 10:37:40 +00:00
xous_kernel ::Message ::MutableBorrow ( msg ) = > QueuedMessage ::MemoryMessageRWLend (
2020-07-15 08:09:42 +00:00
pid . get ( ) as _ ,
context as _ ,
2020-04-01 09:27:59 +00:00
original_address . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) ,
msg . id ,
msg . buf . addr . get ( ) ,
msg . buf . size . get ( ) ,
msg . offset . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) as usize ,
msg . valid . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) as usize ,
) ,
2020-08-17 10:37:40 +00:00
xous_kernel ::Message ::Borrow ( msg ) = > QueuedMessage ::MemoryMessageROLend (
2020-07-15 08:09:42 +00:00
pid . get ( ) as _ ,
context as _ ,
2020-04-01 09:27:59 +00:00
original_address . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) ,
2020-03-31 10:03:19 +00:00
msg . id ,
2020-04-01 02:28:36 +00:00
msg . buf . addr . get ( ) ,
msg . buf . size . get ( ) ,
2020-03-31 10:03:19 +00:00
msg . offset . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) as usize ,
msg . valid . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) as usize ,
2020-03-30 08:07:58 +00:00
) ,
} ;
2020-04-01 09:27:59 +00:00
let idx = self . queue_head ;
2020-03-24 06:13:11 +00:00
self . queue_head + = 1 ;
if self . queue_head > = self . queue . len ( ) {
self . queue_head = 0 ;
}
2020-04-01 09:27:59 +00:00
Ok ( idx )
2020-03-24 06:13:11 +00:00
}
2020-09-23 02:52:22 +00:00
pub fn queue_response (
2020-04-01 09:27:59 +00:00
& mut self ,
pid : PID ,
2020-07-21 01:44:16 +00:00
context : TID ,
2020-04-01 09:27:59 +00:00
message : & Message ,
client_address : Option < MemoryAddress > ,
2020-08-17 10:37:40 +00:00
) -> core ::result ::Result < usize , xous_kernel ::Error > {
2020-11-11 08:04:35 +00:00
// println!("Queueing address message: {:?} (pid: {} tid: {})", message, pid.get(), context);
2020-04-01 09:27:59 +00:00
if self . queue [ self . queue_head ] ! = QueuedMessage ::Empty {
2020-08-17 10:37:40 +00:00
return Err ( xous_kernel ::Error ::ServerQueueFull ) ;
2020-04-01 09:27:59 +00:00
}
2020-09-23 02:52:22 +00:00
self . queue [ self . queue_head ] = match message {
xous_kernel ::Message ::Scalar ( _ ) | xous_kernel ::Message ::BlockingScalar ( _ ) = > {
QueuedMessage ::WaitingReturnScalar (
pid . get ( ) as _ ,
context as _ ,
client_address . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) ,
)
}
xous_kernel ::Message ::Move ( msg ) = > {
let server_address = msg . buf . addr . get ( ) ;
let len = msg . buf . size . get ( ) ;
QueuedMessage ::WaitingForget (
pid . get ( ) as _ ,
context as _ ,
server_address ,
client_address . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) ,
len ,
)
}
2020-08-17 10:37:40 +00:00
xous_kernel ::Message ::MutableBorrow ( msg ) | xous_kernel ::Message ::Borrow ( msg ) = > {
2020-09-23 02:52:22 +00:00
let server_address = msg . buf . addr . get ( ) ;
let len = msg . buf . size . get ( ) ;
QueuedMessage ::WaitingReturnMemory (
pid . get ( ) as _ ,
context as _ ,
server_address ,
client_address . map ( | x | x . get ( ) ) . unwrap_or ( 0 ) ,
len ,
)
2020-04-01 09:27:59 +00:00
}
} ;
let idx = self . queue_head ;
self . queue_head + = 1 ;
if self . queue_head > = self . queue . len ( ) {
self . queue_head = 0 ;
}
Ok ( idx )
}
2020-03-24 06:13:11 +00:00
// assert!(
// mem::size_of::<QueuedMessage>() == 32,
// "QueuedMessage was supposed to be 32 bytes, but instead was {} bytes",
// mem::size_of::<QueuedMessage>()
// );
2020-03-30 04:35:50 +00:00
/// Return a context ID that is available and blocking. If no such context
/// ID exists, or if this server isn't actually ready to receive packets,
/// return None.
2020-07-21 02:01:57 +00:00
pub fn take_available_thread ( & mut self ) -> Option < TID > {
if self . ready_threads = = 0 {
2020-03-24 06:13:11 +00:00
return None ;
}
2020-07-21 07:50:33 +00:00
let mut test_thread_mask = 1 ;
let mut thread_number = 0 ;
2020-11-23 09:24:28 +00:00
klog! ( " ready threads: 0b{:08b} " , self . ready_threads ) ;
2020-03-24 06:13:11 +00:00
loop {
// If the context mask matches this context number, remove it
// and return the index.
2020-07-21 07:50:33 +00:00
if self . ready_threads & test_thread_mask = = test_thread_mask {
self . ready_threads & = ! test_thread_mask ;
return Some ( thread_number ) ;
2020-03-24 06:13:11 +00:00
}
// Advance to the next slot.
2020-07-21 07:50:33 +00:00
test_thread_mask = test_thread_mask . rotate_left ( 1 ) ;
thread_number + = 1 ;
if test_thread_mask = = 1 {
2020-03-24 06:13:11 +00:00
panic! ( " didn't find a free context, even though there should be one " ) ;
}
}
}
2020-03-24 06:52:25 +00:00
2020-04-06 02:43:26 +00:00
/// Return an available context to the blocking list. This is part of the
/// error condition when a message cannot be handled but the context has
/// already been claimed.
///
/// # Panics
///
/// If the context cannot be returned because it is already blocking.
2020-07-21 02:01:57 +00:00
pub fn return_available_thread ( & mut self , tid : TID ) {
if self . ready_threads & 1 < < tid ! = 0 {
2020-06-15 10:13:10 +00:00
panic! (
" tried to return context {}, but it was already blocking " ,
2020-07-21 02:01:57 +00:00
tid
2020-06-15 10:13:10 +00:00
) ;
2020-04-06 02:43:26 +00:00
}
2020-07-21 02:01:57 +00:00
self . ready_threads | = 1 < < tid ;
2020-04-06 02:43:26 +00:00
}
2020-03-30 04:35:50 +00:00
/// Add the given context to the list of ready and waiting contexts.
2020-07-21 02:01:57 +00:00
pub fn park_thread ( & mut self , tid : TID ) {
2020-11-23 09:24:28 +00:00
klog! ( " parking thread {} " , tid ) ;
2020-07-21 07:50:33 +00:00
assert! ( self . ready_threads & ( 1 < < tid ) = = 0 ) ;
2020-07-21 02:01:57 +00:00
self . ready_threads | = 1 < < tid ;
2020-11-23 09:24:28 +00:00
klog! ( " ready threads now: {:08b} " , self . ready_threads ) ;
2020-03-24 06:52:25 +00:00
}
2020-03-24 06:13:11 +00:00
}