diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index 2639e95d3..c8e21e5fd 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -509,6 +509,19 @@ pub unsafe fn main() { attribute_writeback(typeinfo as *const ()); } + // Make sure all async RPCs are processed before exiting. + // Otherwise, if the comms and kernel CPU run in the following sequence: + // + // comms kernel + // ----------------------- ----------------------- + // check for async RPC + // post async RPC + // post RunFinished + // check for mailbox + // + // the async RPC would be missed. + send(&RpcFlush); + send(&RunFinished); loop {} diff --git a/artiq/firmware/libproto/kernel_proto.rs b/artiq/firmware/libproto/kernel_proto.rs index c59306cb8..584c1940e 100644 --- a/artiq/firmware/libproto/kernel_proto.rs +++ b/artiq/firmware/libproto/kernel_proto.rs @@ -74,6 +74,7 @@ pub enum Message<'a> { }, RpcRecvRequest(*mut ()), RpcRecvReply(Result>), + RpcFlush, CacheGetRequest { key: &'a str }, CacheGetReply { value: &'static [i32] }, diff --git a/artiq/firmware/runtime/session.rs b/artiq/firmware/runtime/session.rs index 5a3e30020..f2c21c92c 100644 --- a/artiq/firmware/runtime/session.rs +++ b/artiq/firmware/runtime/session.rs @@ -440,7 +440,13 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>, kern_acknowledge() } } - } + }, + &kern::RpcFlush => { + // See ksupport/lib.rs for the reason this request exists. + // We do not need to do anything here because of how the main loop is + // structured. + kern_acknowledge() + }, &kern::CacheGetRequest { key } => { let value = session.congress.cache.get(key);