Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 6bbaff81bfb1
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2b3bc30396be
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Oct 4, 2016

  1. Copy the full SHA
    0cd87af View commit details
  2. Rust: implement startup kernels.

    whitequark committed Oct 4, 2016
    Copy the full SHA
    2b3bc30 View commit details
Showing with 62 additions and 21 deletions.
  1. +4 −2 artiq/runtime.rs/src/lib.rs
  2. +7 −7 artiq/runtime.rs/src/sched.rs
  3. +51 −12 artiq/runtime.rs/src/session.rs
6 changes: 4 additions & 2 deletions artiq/runtime.rs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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();
14 changes: 7 additions & 7 deletions artiq/runtime.rs/src/sched.rs
Original file line number Diff line number Diff line change
@@ -214,13 +214,6 @@ unsafe impl Send for WaitEvent {}
pub struct Waiter<'a>(&'a Yielder<WaitResult, WaitRequest, OwnedStack>);

impl<'a> Waiter<'a> {
pub fn relinquish(&self) {
self.0.suspend(WaitRequest {
timeout: None,
event: None
});
}

pub fn sleep(&self, duration: Duration) -> Result<()> {
let request = WaitRequest {
timeout: Some(Instant::now() + duration),
@@ -242,6 +235,13 @@ impl<'a> Waiter<'a> {
}
}

pub fn relinquish(&self) -> Result<()> {
self.suspend(WaitRequest {
timeout: None,
event: None
})
}

pub fn join(&self, thread: ThreadHandle) -> Result<()> {
self.suspend(WaitRequest {
timeout: None,
63 changes: 51 additions & 12 deletions artiq/runtime.rs/src/session.rs
Original file line number Diff line number Diff line change
@@ -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<bool> {
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 {
@@ -320,7 +326,7 @@ fn host_kernel_worker(waiter: Waiter,
}
}

waiter.relinquish()
try!(waiter.relinquish())
}
}

@@ -330,11 +336,29 @@ fn flash_kernel_worker(waiter: Waiter,
let mut session = Session::new(congress);

let kernel = config::read_to_end(config_key);
if kernel.len() == 0 {
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())
}
}

@@ -355,9 +379,21 @@ fn respawn<F>(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");
@@ -383,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);
}
}
}
@@ -402,14 +438,17 @@ 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);
}
}
}
})
}

waiter.relinquish()
let _ = waiter.relinquish();
}
}