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 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 { macro_rules! recv {
($p:pat => $e:expr) => { ($p:pat => $e:expr) => {
recv(move |request| { 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) { 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 } => { recv!(&SubkernelLoadRunReply { succeeded } => {
if !succeeded { if !succeeded {
raise!("SubkernelError", raise!("SubkernelError",
@ -601,6 +617,15 @@ pub unsafe fn main() {
}, },
Ok(library) => { Ok(library) => {
send(&LoadReply(Ok(()))); 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 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] }, SubkernelAddDataRequest { destination: u8, id: u32, status: PayloadStatus, length: u16, data: [u8; MASTER_PAYLOAD_MAX_SIZE] },
SubkernelAddDataReply { succeeded: bool }, 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 }, SubkernelLoadRunReply { destination: u8, succeeded: bool },
SubkernelFinished { destination: u8, id: u32, with_exception: bool, exception_src: u8 }, SubkernelFinished { destination: u8, id: u32, with_exception: bool, exception_src: u8 },
SubkernelExceptionRequest { source: u8, destination: u8 }, SubkernelExceptionRequest { source: u8, destination: u8 },
@ -354,7 +354,8 @@ impl Packet {
source: reader.read_u8()?, source: reader.read_u8()?,
destination: reader.read_u8()?, destination: reader.read_u8()?,
id: reader.read_u32()?, id: reader.read_u32()?,
run: reader.read_bool()? run: reader.read_bool()?,
timestamp: reader.read_u64()?
}, },
0xc5 => Packet::SubkernelLoadRunReply { 0xc5 => Packet::SubkernelLoadRunReply {
destination: reader.read_u8()?, destination: reader.read_u8()?,
@ -647,12 +648,13 @@ impl Packet {
writer.write_u8(0xc1)?; writer.write_u8(0xc1)?;
writer.write_bool(succeeded)?; writer.write_bool(succeeded)?;
}, },
Packet::SubkernelLoadRunRequest { source, destination, id, run } => { Packet::SubkernelLoadRunRequest { source, destination, id, run, timestamp } => {
writer.write_u8(0xc4)?; writer.write_u8(0xc4)?;
writer.write_u8(source)?; writer.write_u8(source)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
writer.write_u32(id)?; writer.write_u32(id)?;
writer.write_bool(run)?; writer.write_bool(run)?;
writer.write_u64(timestamp)?;
}, },
Packet::SubkernelLoadRunReply { destination, succeeded } => { Packet::SubkernelLoadRunReply { destination, succeeded } => {
writer.write_u8(0xc5)?; writer.write_u8(0xc5)?;

View File

@ -103,7 +103,7 @@ pub enum Message<'a> {
SpiReadReply { succeeded: bool, data: u32 }, SpiReadReply { succeeded: bool, data: u32 },
SpiBasicReply { succeeded: bool }, SpiBasicReply { succeeded: bool },
SubkernelLoadRunRequest { id: u32, destination: u8, run: bool }, SubkernelLoadRunRequest { id: u32, destination: u8, run: bool, timestamp: u64 },
SubkernelLoadRunReply { succeeded: bool }, SubkernelLoadRunReply { succeeded: bool },
SubkernelAwaitFinishRequest { id: u32, timeout: i64 }, SubkernelAwaitFinishRequest { id: u32, timeout: i64 },
SubkernelAwaitFinishReply, SubkernelAwaitFinishReply,
@ -112,6 +112,8 @@ pub enum Message<'a> {
SubkernelMsgRecvReply { count: u8 }, SubkernelMsgRecvReply { count: u8 },
SubkernelError(SubkernelStatus<'a>), SubkernelError(SubkernelStatus<'a>),
UpdateNow(u64),
Log(fmt::Arguments<'a>), Log(fmt::Arguments<'a>),
LogSlice(&'a str) 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, 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 _lock = subkernel_mutex.lock(io)?;
let subkernel = unsafe { SUBKERNELS.get_mut(&id).unwrap() }; let subkernel = unsafe { SUBKERNELS.get_mut(&id).unwrap() };
if subkernel.state != SubkernelState::Uploaded { if subkernel.state != SubkernelState::Uploaded {
error!("for id: {} expected Uploaded, got: {:?}", id, subkernel.state); error!("for id: {} expected Uploaded, got: {:?}", id, subkernel.state);
return Err(Error::IncorrectState); 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 { if run {
subkernel.state = SubkernelState::Running; 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, 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> { ) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno, 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 { match reply {
drtioaux::Packet::SubkernelLoadRunReply { destination: 0, succeeded: true } => Ok(()), drtioaux::Packet::SubkernelLoadRunReply { destination: 0, succeeded: true } => Ok(()),
drtioaux::Packet::SubkernelLoadRunReply { destination: 0, succeeded: false } => 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)] #[cfg(has_drtio)]
&kern::SubkernelLoadRunRequest { id, destination: _, run } => { &kern::SubkernelLoadRunRequest { id, destination: _, run, timestamp } => {
let succeeded = match subkernel::load( 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, Ok(()) => true,
Err(e) => { error!("Error loading subkernel: {}", e); false } Err(e) => { error!("Error loading subkernel: {}", e); false }
}; };

View File

@ -363,17 +363,17 @@ impl Manager {
unsafe { self.cache.unborrow() } 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); info!("starting subkernel #{}", id);
if self.session.kernel_state != KernelState::Loaded if self.session.kernel_state != KernelState::Loaded
|| self.current_id != id { || self.current_id != id {
self.load(id)?; self.load(id)?;
} }
self.session.source = source; self.session.source = source;
self.session.kernel_state = KernelState::Running; self.session.kernel_state = KernelState::Running;
cricon_select(RtioMaster::Kernel); 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]) { 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 // ID equal to -1 indicates wildcard for receiving arguments
let id = if id == -1 { self.current_id } else { id as u32 }; let id = if id == -1 { self.current_id } else { id as u32 };
self.session.kernel_state = KernelState::MsgAwait { self.session.kernel_state = KernelState::MsgAwait {
id: id, max_time: max_time, tags: tags.to_vec() }; id, max_time, tags: tags.to_vec() };
Ok(()) Ok(())
}, },
&kern::SubkernelLoadRunRequest { id, destination: sk_destination, run } => { &kern::SubkernelLoadRunRequest { id, destination: sk_destination, run, timestamp } => {
self.session.kernel_state = KernelState::SubkernelAwaitLoad; self.session.kernel_state = KernelState::SubkernelAwaitLoad;
router.route(drtioaux::Packet::SubkernelLoadRunRequest { 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); }, routing_table, rank, destination);
Ok(()) Ok(())
} }
&kern::SubkernelAwaitFinishRequest{ id, timeout } => { &kern::SubkernelAwaitFinishRequest { id, timeout } => {
let max_time = if timeout > 0 { clock::get_ms() as i64 + timeout } else { 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(()) Ok(())
} }

View File

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