From 2b3bc30396be26dea5d9e718db0d8eba312bd5e8 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 4 Oct 2016 06:08:08 +0000 Subject: [PATCH] Rust: implement startup kernels. --- artiq/runtime.rs/src/lib.rs | 6 ++-- artiq/runtime.rs/src/session.rs | 60 +++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/artiq/runtime.rs/src/lib.rs b/artiq/runtime.rs/src/lib.rs index 40963f72a..5d73b8a17 100644 --- a/artiq/runtime.rs/src/lib.rs +++ b/artiq/runtime.rs/src/lib.rs @@ -42,14 +42,16 @@ pub unsafe extern fn rust_main() { static mut LOG_BUFFER: [u8; 4096] = [0; 4096]; BufferLogger::new(&mut LOG_BUFFER[..]) .register(move || { - info!("booting ARTIQ runtime ({})", GIT_COMMIT); + info!("booting ARTIQ..."); + info!("software version {}", GIT_COMMIT); + info!("gateware version {}", ::board::ident(&mut [0; 64])); clock::init(); rtio_crg::init(); network_init(); let mut scheduler = sched::Scheduler::new(); - scheduler.spawner().spawn(8192, session::handler); + scheduler.spawner().spawn(8192, session::thread); loop { scheduler.run(); diff --git a/artiq/runtime.rs/src/session.rs b/artiq/runtime.rs/src/session.rs index ad3f9ee94..e4fdf2924 100644 --- a/artiq/runtime.rs/src/session.rs +++ b/artiq/runtime.rs/src/session.rs @@ -208,8 +208,7 @@ fn process_host_message(waiter: Waiter, // artiq_run/artiq_master host::Request::SwitchClock(clk) => { if session.running() { - error!("attempted to switch RTIO clock while a kernel was running"); - return host_write(stream, host::Reply::ClockSwitchFailed) + unexpected!("attempted to switch RTIO clock while a kernel was running") } if rtio_crg::switch_clock(clk) { @@ -236,13 +235,13 @@ fn process_host_message(waiter: Waiter, } fn process_kern_message(waiter: Waiter, - session: &mut Session) -> io::Result<()> { + session: &mut Session) -> io::Result { kern::Message::wait_and_receive(waiter, |request| { match (&request, session.kernel_state) { (&kern::LoadReply { .. }, KernelState::Loaded) | (&kern::RpcRecvRequest { .. }, KernelState::RpcWait) => { // We're standing by; ignore the message. - return Ok(()) + return Ok(false) } (_, KernelState::Running) => (), _ => { @@ -289,8 +288,13 @@ fn process_kern_message(waiter: Waiter, kern_send(waiter, kern::CachePutReply { succeeded: succeeded }) } + kern::RunFinished => { + session.kernel_state = KernelState::Absent; + return Ok(true) + } + request => unexpected!("unexpected request {:?} from kernel CPU", request) - } + }.and(Ok(false)) }) } @@ -305,7 +309,9 @@ fn host_kernel_worker(waiter: Waiter, } if mailbox::receive() != 0 { - try!(process_kern_message(waiter, &mut session)) + if try!(process_kern_message(waiter, &mut session)) { + try!(host_write(stream, host::Reply::KernelFinished)) + } } if session.kernel_state == KernelState::Running { @@ -331,17 +337,28 @@ fn flash_kernel_worker(waiter: Waiter, let kernel = config::read_to_end(config_key); if kernel.len() == 0 { - info!("no kernel present in config key {}", config_key); - loop { - try!(waiter.relinquish()) - } + return Err(io::Error::new(io::ErrorKind::NotFound, "kernel not found")) } try!(unsafe { kern_load(waiter, &mut session, &kernel) }); try!(kern_run(&mut session)); loop { - try!(process_kern_message(waiter, &mut session)) + if mailbox::receive() != 0 { + if try!(process_kern_message(waiter, &mut session)) { + return Ok(()) + } + } + + if session.watchdog_set.expired() { + return Err(io_error("watchdog expired")) + } + + if !rtio_crg::check() { + return Err(io_error("RTIO clock failure")) + } + + try!(waiter.relinquish()) } } @@ -362,9 +379,21 @@ fn respawn(spawner: Spawner, waiter: Waiter, *handle = Some(spawner.spawn(8192, f)) } -pub fn handler(waiter: Waiter, spawner: Spawner) { +pub fn thread(waiter: Waiter, spawner: Spawner) { let congress = Urc::new(RefCell::new(Congress::new())); + info!("running startup kernel"); + match flash_kernel_worker(waiter, &mut congress.borrow_mut(), "startup_kernel") { + Ok(()) => info!("startup kernel finished"), + Err(err) => { + if err.kind() == io::ErrorKind::NotFound { + info!("no startup kernel found") + } else { + error!("startup kernel aborted: {}", err); + } + } + } + let addr = SocketAddr::new(IP_ANY, 1381); let listener = TcpListener::bind(waiter, addr).expect("cannot bind socket"); info!("accepting network sessions in Rust"); @@ -390,7 +419,7 @@ pub fn handler(waiter: Waiter, spawner: Spawner) { if err.kind() == io::ErrorKind::UnexpectedEof { info!("connection closed"); } else { - error!("session aborted: {:?}", err); + error!("session aborted: {}", err); } } } @@ -409,8 +438,11 @@ pub fn handler(waiter: Waiter, spawner: Spawner) { Err(err) => { if err.kind() == io::ErrorKind::Interrupted { info!("idle kernel interrupted"); + } else if err.kind() == io::ErrorKind::NotFound { + info!("no idle kernel found"); + while waiter.relinquish().is_ok() {} } else { - error!("idle kernel aborted: {:?}", err); + error!("idle kernel aborted: {}", err); } } }