subkernels: send now_mu when starting a subkernel

This commit is contained in:
mwojcik 2024-10-18 12:36:09 +08:00 committed by Sébastien Bourdeauducq
parent 33b81d0e2e
commit 4178fed3f7
8 changed files with 54 additions and 21 deletions

View File

@ -37,6 +37,14 @@ fn recv<R, F: FnOnce(&Message) -> R>(f: F) -> R {
result
}
fn try_recv<F: FnOnce(&Message)>(f: F) {
let msg_ptr = mailbox::receive();
if msg_ptr != 0 {
f(unsafe { &*(msg_ptr as *const Message) });
mailbox::acknowledge();
}
}
macro_rules! recv {
($p:pat => $e:expr) => {
recv(move |request| {
@ -473,7 +481,15 @@ extern "C-unwind" fn dma_playback(timestamp: i64, ptr: i32, _uses_ddma: bool) {
extern "C-unwind" fn subkernel_load_run(id: u32, destination: u8, run: bool) {
send(&SubkernelLoadRunRequest { id: id, destination: destination, run: run });
let timestamp = unsafe {
((csr::rtio::now_hi_read() as u64) << 32) | (csr::rtio::now_lo_read() as u64)
};
send(&SubkernelLoadRunRequest {
id: id,
destination: destination,
run: run,
timestamp: timestamp,
});
recv!(&SubkernelLoadRunReply { succeeded } => {
if !succeeded {
raise!("SubkernelError",
@ -601,6 +617,15 @@ pub unsafe fn main() {
},
Ok(library) => {
send(&LoadReply(Ok(())));
// Master kernel would just acknowledge kernel load
// Satellites may send UpdateNow
try_recv(move |msg| match msg {
UpdateNow(timestamp) => unsafe {
csr::rtio::now_hi_write((*timestamp >> 32) as u32);
csr::rtio::now_lo_write(*timestamp as u32);
}
_ => unreachable!()
});
library
}
}

View File

@ -120,7 +120,7 @@ pub enum Packet {
SubkernelAddDataRequest { destination: u8, id: u32, status: PayloadStatus, length: u16, data: [u8; MASTER_PAYLOAD_MAX_SIZE] },
SubkernelAddDataReply { succeeded: bool },
SubkernelLoadRunRequest { source: u8, destination: u8, id: u32, run: bool },
SubkernelLoadRunRequest { source: u8, destination: u8, id: u32, run: bool, timestamp: u64 },
SubkernelLoadRunReply { destination: u8, succeeded: bool },
SubkernelFinished { destination: u8, id: u32, with_exception: bool, exception_src: u8 },
SubkernelExceptionRequest { source: u8, destination: u8 },
@ -354,7 +354,8 @@ impl Packet {
source: reader.read_u8()?,
destination: reader.read_u8()?,
id: reader.read_u32()?,
run: reader.read_bool()?
run: reader.read_bool()?,
timestamp: reader.read_u64()?
},
0xc5 => Packet::SubkernelLoadRunReply {
destination: reader.read_u8()?,
@ -647,12 +648,13 @@ impl Packet {
writer.write_u8(0xc1)?;
writer.write_bool(succeeded)?;
},
Packet::SubkernelLoadRunRequest { source, destination, id, run } => {
Packet::SubkernelLoadRunRequest { source, destination, id, run, timestamp } => {
writer.write_u8(0xc4)?;
writer.write_u8(source)?;
writer.write_u8(destination)?;
writer.write_u32(id)?;
writer.write_bool(run)?;
writer.write_u64(timestamp)?;
},
Packet::SubkernelLoadRunReply { destination, succeeded } => {
writer.write_u8(0xc5)?;

View File

@ -103,7 +103,7 @@ pub enum Message<'a> {
SpiReadReply { succeeded: bool, data: u32 },
SpiBasicReply { succeeded: bool },
SubkernelLoadRunRequest { id: u32, destination: u8, run: bool },
SubkernelLoadRunRequest { id: u32, destination: u8, run: bool, timestamp: u64 },
SubkernelLoadRunReply { succeeded: bool },
SubkernelAwaitFinishRequest { id: u32, timeout: i64 },
SubkernelAwaitFinishReply,
@ -112,6 +112,8 @@ pub enum Message<'a> {
SubkernelMsgRecvReply { count: u8 },
SubkernelError(SubkernelStatus<'a>),
UpdateNow(u64),
Log(fmt::Arguments<'a>),
LogSlice(&'a str)
}

View File

@ -194,14 +194,15 @@ pub mod subkernel {
}
pub fn load(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, subkernel_mutex: &Mutex, routing_table: &RoutingTable,
id: u32, run: bool) -> Result<(), Error> {
id: u32, run: bool, timestamp: u64) -> Result<(), Error> {
let _lock = subkernel_mutex.lock(io)?;
let subkernel = unsafe { SUBKERNELS.get_mut(&id).unwrap() };
if subkernel.state != SubkernelState::Uploaded {
error!("for id: {} expected Uploaded, got: {:?}", id, subkernel.state);
return Err(Error::IncorrectState);
}
drtio::subkernel_load(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, id, subkernel.destination, run)?;
drtio::subkernel_load(io, aux_mutex, ddma_mutex, subkernel_mutex,
routing_table, id, subkernel.destination, run, timestamp)?;
if run {
subkernel.state = SubkernelState::Running;
}

View File

@ -594,11 +594,14 @@ pub mod drtio {
}
pub fn subkernel_load(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
routing_table: &drtio_routing::RoutingTable, id: u32, destination: u8, run: bool
routing_table: &drtio_routing::RoutingTable, id: u32, destination: u8, run: bool, timestamp: u64
) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
&drtioaux::Packet::SubkernelLoadRunRequest{ id: id, source: 0, destination: destination, run: run })?;
&drtioaux::Packet::SubkernelLoadRunRequest{
id: id, source: 0, destination: destination,
run: run, timestamp: timestamp
})?;
match reply {
drtioaux::Packet::SubkernelLoadRunReply { destination: 0, succeeded: true } => Ok(()),
drtioaux::Packet::SubkernelLoadRunReply { destination: 0, succeeded: false } =>

View File

@ -661,9 +661,9 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
}
}
#[cfg(has_drtio)]
&kern::SubkernelLoadRunRequest { id, destination: _, run } => {
&kern::SubkernelLoadRunRequest { id, destination: _, run, timestamp } => {
let succeeded = match subkernel::load(
io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, id, run) {
io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, id, run, timestamp) {
Ok(()) => true,
Err(e) => { error!("Error loading subkernel: {}", e); false }
};

View File

@ -363,7 +363,7 @@ impl Manager {
unsafe { self.cache.unborrow() }
}
pub fn run(&mut self, source: u8, id: u32) -> Result<(), Error> {
pub fn run(&mut self, source: u8, id: u32, timestamp: u64) -> Result<(), Error> {
info!("starting subkernel #{}", id);
if self.session.kernel_state != KernelState::Loaded
|| self.current_id != id {
@ -373,7 +373,7 @@ impl Manager {
self.session.kernel_state = KernelState::Running;
cricon_select(RtioMaster::Kernel);
kern_acknowledge()
kern_send(&kern::UpdateNow(timestamp))
}
pub fn message_handle_incoming(&mut self, status: PayloadStatus, length: usize, id: u32, slice: &[u8; MASTER_PAYLOAD_MAX_SIZE]) {
@ -825,21 +825,21 @@ impl Manager {
// ID equal to -1 indicates wildcard for receiving arguments
let id = if id == -1 { self.current_id } else { id as u32 };
self.session.kernel_state = KernelState::MsgAwait {
id: id, max_time: max_time, tags: tags.to_vec() };
id, max_time, tags: tags.to_vec() };
Ok(())
},
&kern::SubkernelLoadRunRequest { id, destination: sk_destination, run } => {
&kern::SubkernelLoadRunRequest { id, destination: sk_destination, run, timestamp } => {
self.session.kernel_state = KernelState::SubkernelAwaitLoad;
router.route(drtioaux::Packet::SubkernelLoadRunRequest {
source: destination, destination: sk_destination, id: id, run: run
source: destination, destination: sk_destination, id, run, timestamp
}, routing_table, rank, destination);
Ok(())
}
&kern::SubkernelAwaitFinishRequest { id, timeout } => {
let max_time = if timeout > 0 { clock::get_ms() as i64 + timeout } else { timeout };
self.session.kernel_state = KernelState::SubkernelAwaitFinish { max_time: max_time, id: id };
self.session.kernel_state = KernelState::SubkernelAwaitFinish { max_time, id };
Ok(())
}

View File

@ -427,7 +427,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg
drtioaux::send(0,
&drtioaux::Packet::SubkernelAddDataReply { succeeded: succeeded })
}
drtioaux::Packet::SubkernelLoadRunRequest { source, destination: _destination, id, run } => {
drtioaux::Packet::SubkernelLoadRunRequest { source, destination: _destination, id, run, timestamp } => {
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
let mut succeeded = kernelmgr.load(id).is_ok();
// allow preloading a kernel with delayed run
@ -436,7 +436,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg
// cannot run kernel while DDMA is running
succeeded = false;
} else {
succeeded |= kernelmgr.run(source, id).is_ok();
succeeded |= kernelmgr.run(source, id, timestamp).is_ok();
}
}
router.send(drtioaux::Packet::SubkernelLoadRunReply {