Rust: implement startup kernels.

This commit is contained in:
whitequark 2016-10-04 06:08:08 +00:00
parent 0cd87af386
commit 2b3bc30396
2 changed files with 50 additions and 16 deletions

View File

@ -42,14 +42,16 @@ pub unsafe extern fn rust_main() {
static mut LOG_BUFFER: [u8; 4096] = [0; 4096]; static mut LOG_BUFFER: [u8; 4096] = [0; 4096];
BufferLogger::new(&mut LOG_BUFFER[..]) BufferLogger::new(&mut LOG_BUFFER[..])
.register(move || { .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(); clock::init();
rtio_crg::init(); rtio_crg::init();
network_init(); network_init();
let mut scheduler = sched::Scheduler::new(); let mut scheduler = sched::Scheduler::new();
scheduler.spawner().spawn(8192, session::handler); scheduler.spawner().spawn(8192, session::thread);
loop { loop {
scheduler.run(); scheduler.run();

View File

@ -208,8 +208,7 @@ fn process_host_message(waiter: Waiter,
// artiq_run/artiq_master // artiq_run/artiq_master
host::Request::SwitchClock(clk) => { host::Request::SwitchClock(clk) => {
if session.running() { if session.running() {
error!("attempted to switch RTIO clock while a kernel was running"); unexpected!("attempted to switch RTIO clock while a kernel was running")
return host_write(stream, host::Reply::ClockSwitchFailed)
} }
if rtio_crg::switch_clock(clk) { if rtio_crg::switch_clock(clk) {
@ -236,13 +235,13 @@ fn process_host_message(waiter: Waiter,
} }
fn process_kern_message(waiter: Waiter, fn process_kern_message(waiter: Waiter,
session: &mut Session) -> io::Result<()> { session: &mut Session) -> io::Result<bool> {
kern::Message::wait_and_receive(waiter, |request| { kern::Message::wait_and_receive(waiter, |request| {
match (&request, session.kernel_state) { match (&request, session.kernel_state) {
(&kern::LoadReply { .. }, KernelState::Loaded) | (&kern::LoadReply { .. }, KernelState::Loaded) |
(&kern::RpcRecvRequest { .. }, KernelState::RpcWait) => { (&kern::RpcRecvRequest { .. }, KernelState::RpcWait) => {
// We're standing by; ignore the message. // We're standing by; ignore the message.
return Ok(()) return Ok(false)
} }
(_, KernelState::Running) => (), (_, KernelState::Running) => (),
_ => { _ => {
@ -289,8 +288,13 @@ fn process_kern_message(waiter: Waiter,
kern_send(waiter, kern::CachePutReply { succeeded: succeeded }) 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) 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 { 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 { if session.kernel_state == KernelState::Running {
@ -331,17 +337,28 @@ fn flash_kernel_worker(waiter: Waiter,
let kernel = config::read_to_end(config_key); let kernel = config::read_to_end(config_key);
if kernel.len() == 0 { if kernel.len() == 0 {
info!("no kernel present in config key {}", config_key); return Err(io::Error::new(io::ErrorKind::NotFound, "kernel not found"))
loop {
try!(waiter.relinquish())
}
} }
try!(unsafe { kern_load(waiter, &mut session, &kernel) }); try!(unsafe { kern_load(waiter, &mut session, &kernel) });
try!(kern_run(&mut session)); try!(kern_run(&mut session));
loop { 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<F>(spawner: Spawner, waiter: Waiter,
*handle = Some(spawner.spawn(8192, f)) *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())); 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 addr = SocketAddr::new(IP_ANY, 1381);
let listener = TcpListener::bind(waiter, addr).expect("cannot bind socket"); let listener = TcpListener::bind(waiter, addr).expect("cannot bind socket");
info!("accepting network sessions in Rust"); info!("accepting network sessions in Rust");
@ -390,7 +419,7 @@ pub fn handler(waiter: Waiter, spawner: Spawner) {
if err.kind() == io::ErrorKind::UnexpectedEof { if err.kind() == io::ErrorKind::UnexpectedEof {
info!("connection closed"); info!("connection closed");
} else { } else {
error!("session aborted: {:?}", err); error!("session aborted: {}", err);
} }
} }
} }
@ -409,8 +438,11 @@ pub fn handler(waiter: Waiter, spawner: Spawner) {
Err(err) => { Err(err) => {
if err.kind() == io::ErrorKind::Interrupted { if err.kind() == io::ErrorKind::Interrupted {
info!("idle kernel interrupted"); info!("idle kernel interrupted");
} else if err.kind() == io::ErrorKind::NotFound {
info!("no idle kernel found");
while waiter.relinquish().is_ok() {}
} else { } else {
error!("idle kernel aborted: {:?}", err); error!("idle kernel aborted: {}", err);
} }
} }
} }