forked from M-Labs/artiq
satman: support free subkernel message passing
This commit is contained in:
parent
171c7a6e11
commit
7d3bcc7cac
|
@ -1,5 +1,5 @@
|
||||||
use core::{mem, option::NoneError};
|
use core::{mem, option::NoneError};
|
||||||
use alloc::{string::String, format, vec::Vec, collections::{btree_map::BTreeMap, vec_deque::VecDeque}};
|
use alloc::{string::String, format, vec::Vec, collections::btree_map::BTreeMap};
|
||||||
use cslice::AsCSlice;
|
use cslice::AsCSlice;
|
||||||
|
|
||||||
use board_artiq::{drtioaux, drtio_routing::RoutingTable, mailbox, spi};
|
use board_artiq::{drtioaux, drtio_routing::RoutingTable, mailbox, spi};
|
||||||
|
@ -63,7 +63,7 @@ enum KernelState {
|
||||||
Absent,
|
Absent,
|
||||||
Loaded,
|
Loaded,
|
||||||
Running,
|
Running,
|
||||||
MsgAwait { max_time: u64, tags: Vec<u8> },
|
MsgAwait { id: u32, max_time: u64, tags: Vec<u8> },
|
||||||
MsgSending,
|
MsgSending,
|
||||||
SubkernelAwaitLoad,
|
SubkernelAwaitLoad,
|
||||||
SubkernelAwaitFinish { max_time: u64, id: u32 },
|
SubkernelAwaitFinish { max_time: u64, id: u32 },
|
||||||
|
@ -115,6 +115,7 @@ macro_rules! unexpected {
|
||||||
|
|
||||||
/* represents interkernel messages */
|
/* represents interkernel messages */
|
||||||
struct Message {
|
struct Message {
|
||||||
|
id: u32,
|
||||||
count: u8,
|
count: u8,
|
||||||
data: Vec<u8>
|
data: Vec<u8>
|
||||||
}
|
}
|
||||||
|
@ -131,7 +132,7 @@ enum OutMessageState {
|
||||||
struct MessageManager {
|
struct MessageManager {
|
||||||
out_message: Option<Sliceable>,
|
out_message: Option<Sliceable>,
|
||||||
out_state: OutMessageState,
|
out_state: OutMessageState,
|
||||||
in_queue: VecDeque<Message>,
|
in_queue: Vec<Message>,
|
||||||
in_buffer: Option<Message>,
|
in_buffer: Option<Message>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,12 +172,12 @@ impl MessageManager {
|
||||||
MessageManager {
|
MessageManager {
|
||||||
out_message: None,
|
out_message: None,
|
||||||
out_state: OutMessageState::NoMessage,
|
out_state: OutMessageState::NoMessage,
|
||||||
in_queue: VecDeque::new(),
|
in_queue: Vec::new(),
|
||||||
in_buffer: None
|
in_buffer: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_incoming(&mut self, status: PayloadStatus, length: usize, data: &[u8; MASTER_PAYLOAD_MAX_SIZE]) {
|
pub fn handle_incoming(&mut self, status: PayloadStatus, length: usize, id: u32, data: &[u8; MASTER_PAYLOAD_MAX_SIZE]) {
|
||||||
// called when receiving a message from master
|
// called when receiving a message from master
|
||||||
if status.is_first() {
|
if status.is_first() {
|
||||||
// clear the buffer for first message
|
// clear the buffer for first message
|
||||||
|
@ -186,6 +187,7 @@ impl MessageManager {
|
||||||
Some(message) => message.data.extend(&data[..length]),
|
Some(message) => message.data.extend(&data[..length]),
|
||||||
None => {
|
None => {
|
||||||
self.in_buffer = Some(Message {
|
self.in_buffer = Some(Message {
|
||||||
|
id: id,
|
||||||
count: data[0],
|
count: data[0],
|
||||||
data: data[1..length].to_vec()
|
data: data[1..length].to_vec()
|
||||||
});
|
});
|
||||||
|
@ -193,7 +195,7 @@ impl MessageManager {
|
||||||
};
|
};
|
||||||
if status.is_last() {
|
if status.is_last() {
|
||||||
// when done, remove from working queue
|
// when done, remove from working queue
|
||||||
self.in_queue.push_back(self.in_buffer.take().unwrap());
|
self.in_queue.push(self.in_buffer.take().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,8 +259,13 @@ impl MessageManager {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_incoming(&mut self) -> Option<Message> {
|
pub fn get_incoming(&mut self, id: u32) -> Option<Message> {
|
||||||
self.in_queue.pop_front()
|
for i in 0..self.in_queue.len() {
|
||||||
|
if self.in_queue[i].id == id {
|
||||||
|
return Some(self.in_queue.remove(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,11 +370,11 @@ impl Manager {
|
||||||
kern_acknowledge()
|
kern_acknowledge()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message_handle_incoming(&mut self, status: PayloadStatus, length: usize, slice: &[u8; MASTER_PAYLOAD_MAX_SIZE]) {
|
pub fn message_handle_incoming(&mut self, status: PayloadStatus, length: usize, id: u32, slice: &[u8; MASTER_PAYLOAD_MAX_SIZE]) {
|
||||||
if !self.is_running() {
|
if !self.is_running() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.session.messages.handle_incoming(status, length, slice);
|
self.session.messages.handle_incoming(status, length, id, slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message_get_slice(&mut self, slice: &mut [u8; MASTER_PAYLOAD_MAX_SIZE]) -> Option<SliceMeta> {
|
pub fn message_get_slice(&mut self, slice: &mut [u8; MASTER_PAYLOAD_MAX_SIZE]) -> Option<SliceMeta> {
|
||||||
|
@ -539,13 +546,13 @@ impl Manager {
|
||||||
|
|
||||||
fn process_external_messages(&mut self) -> Result<(), Error> {
|
fn process_external_messages(&mut self) -> Result<(), Error> {
|
||||||
match &self.session.kernel_state {
|
match &self.session.kernel_state {
|
||||||
KernelState::MsgAwait { max_time, tags } => {
|
KernelState::MsgAwait { id, max_time, tags } => {
|
||||||
if clock::get_ms() > *max_time {
|
if clock::get_ms() > *max_time {
|
||||||
kern_send(&kern::SubkernelMsgRecvReply { status: kern::SubkernelStatus::Timeout, count: 0 })?;
|
kern_send(&kern::SubkernelMsgRecvReply { status: kern::SubkernelStatus::Timeout, count: 0 })?;
|
||||||
self.session.kernel_state = KernelState::Running;
|
self.session.kernel_state = KernelState::Running;
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
if let Some(message) = self.session.messages.get_incoming() {
|
if let Some(message) = self.session.messages.get_incoming(*id) {
|
||||||
kern_send(&kern::SubkernelMsgRecvReply { status: kern::SubkernelStatus::NoError, count: message.count })?;
|
kern_send(&kern::SubkernelMsgRecvReply { status: kern::SubkernelStatus::NoError, count: message.count })?;
|
||||||
let tags = tags.clone();
|
let tags = tags.clone();
|
||||||
self.session.kernel_state = KernelState::Running;
|
self.session.kernel_state = KernelState::Running;
|
||||||
|
@ -752,22 +759,29 @@ impl Manager {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
&kern::SubkernelMsgSend { id: _, destination: msg_dest, count, tag, data } => {
|
&kern::SubkernelMsgSend { id, destination: msg_dest, count, tag, data } => {
|
||||||
let dest = match msg_dest {
|
let message_destination;
|
||||||
Some(dest) => dest,
|
let message_id;
|
||||||
None => self.session.source
|
if let Some(dest) = msg_dest {
|
||||||
};
|
message_destination = dest;
|
||||||
self.session.messages.accept_outgoing(self.current_id, destination,
|
message_id = id;
|
||||||
dest, count, tag, data,
|
} else {
|
||||||
|
// return message, return to source
|
||||||
|
message_destination = self.session.source;
|
||||||
|
message_id = self.current_id;
|
||||||
|
}
|
||||||
|
self.session.messages.accept_outgoing(message_id, destination,
|
||||||
|
message_destination, count, tag, data,
|
||||||
routing_table, rank, router)?;
|
routing_table, rank, router)?;
|
||||||
// acknowledge after the message is sent
|
// acknowledge after the message is sent
|
||||||
self.session.kernel_state = KernelState::MsgSending;
|
self.session.kernel_state = KernelState::MsgSending;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
&kern::SubkernelMsgRecvRequest { id: _, timeout, tags } => {
|
&kern::SubkernelMsgRecvRequest { id, timeout, tags } => {
|
||||||
let max_time = clock::get_ms() + timeout as u64;
|
let max_time = clock::get_ms() + timeout as u64;
|
||||||
self.session.kernel_state = KernelState::MsgAwait { max_time: max_time, tags: tags.to_vec() };
|
self.session.kernel_state = KernelState::MsgAwait {
|
||||||
|
id: id, max_time: max_time, tags: tags.to_vec() };
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -458,9 +458,9 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg
|
||||||
data: data_slice,
|
data: data_slice,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
drtioaux::Packet::SubkernelMessage { source, destination: _destination, id: _id, status, length, data } => {
|
drtioaux::Packet::SubkernelMessage { source, destination: _destination, id, status, length, data } => {
|
||||||
forward!(_routing_table, _destination, *rank, _repeaters, &packet);
|
forward!(_routing_table, _destination, *rank, _repeaters, &packet);
|
||||||
kernelmgr.message_handle_incoming(status, length as usize, &data);
|
kernelmgr.message_handle_incoming(status, length as usize, id, &data);
|
||||||
router.send(drtioaux::Packet::SubkernelMessageAck {
|
router.send(drtioaux::Packet::SubkernelMessageAck {
|
||||||
destination: source
|
destination: source
|
||||||
}, _routing_table, *rank, *self_destination)
|
}, _routing_table, *rank, *self_destination)
|
||||||
|
|
Loading…
Reference in New Issue