forked from M-Labs/artiq
firmware: use dedicated error types for every protocol and thread.
Good riddance to io::Error::Unrecognized.
This commit is contained in:
parent
514eab3d39
commit
479cb9a857
|
@ -208,6 +208,7 @@ dependencies = [
|
||||||
"failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"io 0.0.0",
|
"io 0.0.0",
|
||||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"std_artiq 0.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -226,6 +227,8 @@ dependencies = [
|
||||||
"build_misoc 0.0.0",
|
"build_misoc 0.0.0",
|
||||||
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fringe 1.1.0 (git+https://github.com/m-labs/libfringe?rev=bd23494)",
|
"fringe 1.1.0 (git+https://github.com/m-labs/libfringe?rev=bd23494)",
|
||||||
"io 0.0.0",
|
"io 0.0.0",
|
||||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -270,6 +273,9 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "std_artiq"
|
name = "std_artiq"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
|
|
|
@ -18,13 +18,13 @@ mod proto;
|
||||||
pub use cursor::Cursor;
|
pub use cursor::Cursor;
|
||||||
#[cfg(feature = "byteorder")]
|
#[cfg(feature = "byteorder")]
|
||||||
pub use proto::{ProtoRead, ProtoWrite};
|
pub use proto::{ProtoRead, ProtoWrite};
|
||||||
|
#[cfg(all(feature = "byteorder", feature = "alloc"))]
|
||||||
|
pub use proto::ReadStringError;
|
||||||
|
|
||||||
#[derive(Fail, Debug, Clone, PartialEq)]
|
#[derive(Fail, Debug, Clone, PartialEq)]
|
||||||
pub enum Error<T> {
|
pub enum Error<T> {
|
||||||
#[fail(display = "unexpected end of stream")]
|
#[fail(display = "unexpected end of stream")]
|
||||||
UnexpectedEnd,
|
UnexpectedEnd,
|
||||||
#[fail(display = "unrecognized input")]
|
|
||||||
Unrecognized,
|
|
||||||
#[fail(display = "{}", _0)]
|
#[fail(display = "{}", _0)]
|
||||||
Other(#[cause] T)
|
Other(#[cause] T)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,22 +8,11 @@ use ::{Read, Write, Error as IoError};
|
||||||
#[derive(Fail, Debug, Clone, PartialEq)]
|
#[derive(Fail, Debug, Clone, PartialEq)]
|
||||||
pub enum ReadStringError<T> {
|
pub enum ReadStringError<T> {
|
||||||
#[fail(display = "invalid UTF-8: {}", _0)]
|
#[fail(display = "invalid UTF-8: {}", _0)]
|
||||||
Utf8Error(Utf8Error),
|
Utf8(Utf8Error),
|
||||||
#[fail(display = "{}", _0)]
|
#[fail(display = "{}", _0)]
|
||||||
Other(T)
|
Other(T)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
impl<T> From<ReadStringError<IoError<T>>> for IoError<T>
|
|
||||||
{
|
|
||||||
fn from(value: ReadStringError<IoError<T>>) -> IoError<T> {
|
|
||||||
match value {
|
|
||||||
ReadStringError::Utf8Error(_) => IoError::Unrecognized,
|
|
||||||
ReadStringError::Other(err) => err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ProtoRead {
|
pub trait ProtoRead {
|
||||||
type ReadError;
|
type ReadError;
|
||||||
|
|
||||||
|
@ -75,7 +64,7 @@ pub trait ProtoRead {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_string(&mut self) -> Result<::alloc::String, ReadStringError<Self::ReadError>> {
|
fn read_string(&mut self) -> Result<::alloc::String, ReadStringError<Self::ReadError>> {
|
||||||
let bytes = self.read_bytes().map_err(ReadStringError::Other)?;
|
let bytes = self.read_bytes().map_err(ReadStringError::Other)?;
|
||||||
String::from_utf8(bytes).map_err(|err| ReadStringError::Utf8Error(err.utf8_error()))
|
String::from_utf8(bytes).map_err(|err| ReadStringError::Utf8(err.utf8_error()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ cslice = { version = "0.3" }
|
||||||
log = { version = "0.4", default-features = false, optional = true }
|
log = { version = "0.4", default-features = false, optional = true }
|
||||||
io = { path = "../libio", features = ["byteorder"] }
|
io = { path = "../libio", features = ["byteorder"] }
|
||||||
dyld = { path = "../libdyld" }
|
dyld = { path = "../libdyld" }
|
||||||
|
# TODO: remove
|
||||||
|
std_artiq = { path = "../libstd_artiq", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
alloc = ["io/alloc"]
|
alloc = ["io/alloc", "std_artiq"]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use io::{Write, ProtoWrite, Error};
|
use io::{Write, ProtoWrite, Error as IoError};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
|
@ -10,7 +10,9 @@ pub struct Header {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Header {
|
impl Header {
|
||||||
pub fn write_to<T: Write>(&self, writer: &mut T) -> Result<(), Error<T::WriteError>> {
|
pub fn write_to<W>(&self, writer: &mut W) -> Result<(), IoError<W::WriteError>>
|
||||||
|
where W: Write + ?Sized
|
||||||
|
{
|
||||||
writer.write_u32(self.sent_bytes)?;
|
writer.write_u32(self.sent_bytes)?;
|
||||||
writer.write_u64(self.total_byte_count)?;
|
writer.write_u64(self.total_byte_count)?;
|
||||||
writer.write_u8(self.overflow_occurred as u8)?;
|
writer.write_u8(self.overflow_occurred as u8)?;
|
||||||
|
|
|
@ -1,4 +1,18 @@
|
||||||
use io::{Read, ProtoRead, Write, ProtoWrite, Error};
|
use io::{Read, ProtoRead, Write, ProtoWrite, Error as IoError};
|
||||||
|
|
||||||
|
#[derive(Fail, Debug)]
|
||||||
|
pub enum Error<T> {
|
||||||
|
#[fail(display = "unknown packet {:#02x}", _0)]
|
||||||
|
UnknownPacket(u8),
|
||||||
|
#[fail(display = "{}", _0)]
|
||||||
|
Io(#[cause] IoError<T>)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<IoError<T>> for Error<T> {
|
||||||
|
fn from(value: IoError<T>) -> Error<T> {
|
||||||
|
Error::Io(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Packet {
|
pub enum Packet {
|
||||||
|
@ -36,7 +50,9 @@ pub enum Packet {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Packet {
|
impl Packet {
|
||||||
pub fn read_from<T: Read>(reader: &mut T) -> Result<Self, Error<T::ReadError>> {
|
pub fn read_from<R>(reader: &mut R) -> Result<Self, Error<R::ReadError>>
|
||||||
|
where R: Read + ?Sized
|
||||||
|
{
|
||||||
Ok(match reader.read_u8()? {
|
Ok(match reader.read_u8()? {
|
||||||
0x00 => Packet::EchoRequest,
|
0x00 => Packet::EchoRequest,
|
||||||
0x01 => Packet::EchoReply,
|
0x01 => Packet::EchoReply,
|
||||||
|
@ -129,11 +145,13 @@ impl Packet {
|
||||||
succeeded: reader.read_bool()?
|
succeeded: reader.read_bool()?
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => return Err(Error::Unrecognized)
|
ty => return Err(Error::UnknownPacket(ty))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to<T: Write>(&self, writer: &mut T) -> Result<(), Error<T::WriteError>> {
|
pub fn write_to<W>(&self, writer: &mut W) -> Result<(), IoError<W::WriteError>>
|
||||||
|
where W: Write + ?Sized
|
||||||
|
{
|
||||||
match *self {
|
match *self {
|
||||||
Packet::EchoRequest =>
|
Packet::EchoRequest =>
|
||||||
writer.write_u8(0x00)?,
|
writer.write_u8(0x00)?,
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![cfg_attr(feature = "alloc", feature(alloc))]
|
#![cfg_attr(feature = "alloc", feature(alloc))]
|
||||||
|
|
||||||
|
extern crate failure;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate failure_derive;
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate cslice;
|
extern crate cslice;
|
||||||
|
@ -8,6 +11,8 @@ extern crate cslice;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
|
#[cfg(feature = "std_artiq")]
|
||||||
|
extern crate std_artiq;
|
||||||
extern crate io;
|
extern crate io;
|
||||||
extern crate dyld;
|
extern crate dyld;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,46 @@ use alloc::Vec;
|
||||||
#[cfg(feature = "log")]
|
#[cfg(feature = "log")]
|
||||||
use log;
|
use log;
|
||||||
|
|
||||||
use io::{Read, ProtoRead, Write, ProtoWrite, Error};
|
use io::{Read, ProtoRead, Write, ProtoWrite, Error as IoError};
|
||||||
|
|
||||||
|
#[derive(Fail, Debug)]
|
||||||
|
pub enum Error<T> {
|
||||||
|
#[fail(display = "incorrect magic")]
|
||||||
|
WrongMagic,
|
||||||
|
#[fail(display = "unknown packet {:#02x}", _0)]
|
||||||
|
UnknownPacket(u8),
|
||||||
|
#[fail(display = "unknown log level {}", _0)]
|
||||||
|
UnknownLogLevel(u8),
|
||||||
|
#[fail(display = "{}", _0)]
|
||||||
|
Io(#[cause] IoError<T>)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<IoError<T>> for Error<T> {
|
||||||
|
fn from(value: IoError<T>) -> Error<T> {
|
||||||
|
Error::Io(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std_artiq")]
|
||||||
|
impl From<::std_artiq::io::Error> for Error<::std_artiq::io::Error> {
|
||||||
|
fn from(value: ::std_artiq::io::Error) -> Error<::std_artiq::io::Error> {
|
||||||
|
Error::Io(IoError::Other(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_magic<R>(reader: &mut R) -> Result<(), Error<R::ReadError>>
|
||||||
|
where R: Read + ?Sized
|
||||||
|
{
|
||||||
|
const MAGIC: &'static [u8] = b"ARTIQ management\n";
|
||||||
|
|
||||||
|
let mut magic: [u8; 17] = [0; 17];
|
||||||
|
reader.read_exact(&mut magic)?;
|
||||||
|
if magic != MAGIC {
|
||||||
|
Err(Error::WrongMagic)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Request {
|
pub enum Request {
|
||||||
|
@ -40,7 +79,9 @@ pub enum Reply<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Request {
|
impl Request {
|
||||||
pub fn read_from<T: Read + ?Sized>(reader: &mut T) -> Result<Self, Error<T::ReadError>> {
|
pub fn read_from<R>(reader: &mut R) -> Result<Self, Error<R::ReadError>>
|
||||||
|
where R: Read + ?Sized
|
||||||
|
{
|
||||||
#[cfg(feature = "log")]
|
#[cfg(feature = "log")]
|
||||||
fn read_log_level_filter<T: Read + ?Sized>(reader: &mut T) ->
|
fn read_log_level_filter<T: Read + ?Sized>(reader: &mut T) ->
|
||||||
Result<log::LevelFilter, Error<T::ReadError>> {
|
Result<log::LevelFilter, Error<T::ReadError>> {
|
||||||
|
@ -51,7 +92,7 @@ impl Request {
|
||||||
3 => log::LevelFilter::Info,
|
3 => log::LevelFilter::Info,
|
||||||
4 => log::LevelFilter::Debug,
|
4 => log::LevelFilter::Debug,
|
||||||
5 => log::LevelFilter::Trace,
|
5 => log::LevelFilter::Trace,
|
||||||
_ => return Err(Error::Unrecognized)
|
lv => return Err(Error::UnknownLogLevel(lv))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,13 +114,15 @@ impl Request {
|
||||||
4 => Request::Hotswap(reader.read_bytes()?),
|
4 => Request::Hotswap(reader.read_bytes()?),
|
||||||
5 => Request::Reboot,
|
5 => Request::Reboot,
|
||||||
8 => Request::DebugAllocator,
|
8 => Request::DebugAllocator,
|
||||||
_ => return Err(Error::Unrecognized)
|
ty => return Err(Error::UnknownPacket(ty))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Reply<'a> {
|
impl<'a> Reply<'a> {
|
||||||
pub fn write_to<T: Write + ?Sized>(&self, writer: &mut T) -> Result<(), Error<T::WriteError>> {
|
pub fn write_to<W>(&self, writer: &mut W) -> Result<(), IoError<W::WriteError>>
|
||||||
|
where W: Write + ?Sized
|
||||||
|
{
|
||||||
match *self {
|
match *self {
|
||||||
Reply::Success => {
|
Reply::Success => {
|
||||||
writer.write_u8(1)?;
|
writer.write_u8(1)?;
|
||||||
|
|
|
@ -1,4 +1,41 @@
|
||||||
use io::{Read, ProtoRead, Write, ProtoWrite, Error};
|
use io::{Read, ProtoRead, Write, ProtoWrite, Error as IoError};
|
||||||
|
|
||||||
|
#[derive(Fail, Debug)]
|
||||||
|
pub enum Error<T> {
|
||||||
|
#[fail(display = "incorrect magic")]
|
||||||
|
WrongMagic,
|
||||||
|
#[fail(display = "unknown packet {:#02x}", _0)]
|
||||||
|
UnknownPacket(u8),
|
||||||
|
#[fail(display = "{}", _0)]
|
||||||
|
Io(#[cause] IoError<T>)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<IoError<T>> for Error<T> {
|
||||||
|
fn from(value: IoError<T>) -> Error<T> {
|
||||||
|
Error::Io(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std_artiq")]
|
||||||
|
impl From<::std_artiq::io::Error> for Error<::std_artiq::io::Error> {
|
||||||
|
fn from(value: ::std_artiq::io::Error) -> Error<::std_artiq::io::Error> {
|
||||||
|
Error::Io(IoError::Other(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_magic<R>(reader: &mut R) -> Result<(), Error<R::ReadError>>
|
||||||
|
where R: Read + ?Sized
|
||||||
|
{
|
||||||
|
const MAGIC: &'static [u8] = b"ARTIQ moninj\n";
|
||||||
|
|
||||||
|
let mut magic: [u8; 13] = [0; 13];
|
||||||
|
reader.read_exact(&mut magic)?;
|
||||||
|
if magic != MAGIC {
|
||||||
|
Err(Error::WrongMagic)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum HostMessage {
|
pub enum HostMessage {
|
||||||
|
@ -14,7 +51,9 @@ pub enum DeviceMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HostMessage {
|
impl HostMessage {
|
||||||
pub fn read_from<T: Read + ?Sized>(reader: &mut T) -> Result<Self, Error<T::ReadError>> {
|
pub fn read_from<R>(reader: &mut R) -> Result<Self, Error<R::ReadError>>
|
||||||
|
where R: Read + ?Sized
|
||||||
|
{
|
||||||
Ok(match reader.read_u8()? {
|
Ok(match reader.read_u8()? {
|
||||||
0 => HostMessage::Monitor {
|
0 => HostMessage::Monitor {
|
||||||
enable: if reader.read_u8()? == 0 { false } else { true },
|
enable: if reader.read_u8()? == 0 { false } else { true },
|
||||||
|
@ -30,13 +69,15 @@ impl HostMessage {
|
||||||
channel: reader.read_u32()?,
|
channel: reader.read_u32()?,
|
||||||
overrd: reader.read_u8()?
|
overrd: reader.read_u8()?
|
||||||
},
|
},
|
||||||
_ => return Err(Error::Unrecognized)
|
ty => return Err(Error::UnknownPacket(ty))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceMessage {
|
impl DeviceMessage {
|
||||||
pub fn write_to<T: Write + ?Sized>(&self, writer: &mut T) -> Result<(), Error<T::WriteError>> {
|
pub fn write_to<W>(&self, writer: &mut W) -> Result<(), IoError<W::WriteError>>
|
||||||
|
where W: Write + ?Sized
|
||||||
|
{
|
||||||
match *self {
|
match *self {
|
||||||
DeviceMessage::MonitorStatus { channel, probe, value } => {
|
DeviceMessage::MonitorStatus { channel, probe, value } => {
|
||||||
writer.write_u8(0)?;
|
writer.write_u8(0)?;
|
||||||
|
|
|
@ -4,10 +4,11 @@ use cslice::{CSlice, CMutSlice};
|
||||||
use io::{ProtoRead, Read, Write, ProtoWrite, Error};
|
use io::{ProtoRead, Read, Write, ProtoWrite, Error};
|
||||||
use self::tag::{Tag, TagIterator, split_tag};
|
use self::tag::{Tag, TagIterator, split_tag};
|
||||||
|
|
||||||
unsafe fn recv_value<T>(reader: &mut T, tag: Tag, data: &mut *mut (),
|
unsafe fn recv_value<R, E>(reader: &mut R, tag: Tag, data: &mut *mut (),
|
||||||
alloc: &Fn(usize) -> Result<*mut (), Error<T::ReadError>>)
|
alloc: &Fn(usize) -> Result<*mut (), E>)
|
||||||
-> Result<(), Error<T::ReadError>>
|
-> Result<(), E>
|
||||||
where T: Read + ?Sized
|
where R: Read + ?Sized,
|
||||||
|
E: From<Error<R::ReadError>>
|
||||||
{
|
{
|
||||||
macro_rules! consume_value {
|
macro_rules! consume_value {
|
||||||
($ty:ty, |$ptr:ident| $map:expr) => ({
|
($ty:ty, |$ptr:ident| $map:expr) => ({
|
||||||
|
@ -74,10 +75,11 @@ unsafe fn recv_value<T>(reader: &mut T, tag: Tag, data: &mut *mut (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_return<T>(reader: &mut T, tag_bytes: &[u8], data: *mut (),
|
pub fn recv_return<R, E>(reader: &mut R, tag_bytes: &[u8], data: *mut (),
|
||||||
alloc: &Fn(usize) -> Result<*mut (), Error<T::ReadError>>)
|
alloc: &Fn(usize) -> Result<*mut (), E>)
|
||||||
-> Result<(), Error<T::ReadError>>
|
-> Result<(), E>
|
||||||
where T: Read + ?Sized
|
where R: Read + ?Sized,
|
||||||
|
E: From<Error<R::ReadError>>
|
||||||
{
|
{
|
||||||
let mut it = TagIterator::new(tag_bytes);
|
let mut it = TagIterator::new(tag_bytes);
|
||||||
#[cfg(feature = "log")]
|
#[cfg(feature = "log")]
|
||||||
|
@ -90,9 +92,9 @@ pub fn recv_return<T>(reader: &mut T, tag_bytes: &[u8], data: *mut (),
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn send_value<T>(writer: &mut T, tag: Tag, data: &mut *const ())
|
unsafe fn send_value<W>(writer: &mut W, tag: Tag, data: &mut *const ())
|
||||||
-> Result<(), Error<T::WriteError>>
|
-> Result<(), Error<W::WriteError>>
|
||||||
where T: Write + ?Sized
|
where W: Write + ?Sized
|
||||||
{
|
{
|
||||||
macro_rules! consume_value {
|
macro_rules! consume_value {
|
||||||
($ty:ty, |$ptr:ident| $map:expr) => ({
|
($ty:ty, |$ptr:ident| $map:expr) => ({
|
||||||
|
@ -167,9 +169,9 @@ unsafe fn send_value<T>(writer: &mut T, tag: Tag, data: &mut *const ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_args<T>(writer: &mut T, service: u32, tag_bytes: &[u8], data: *const *const ())
|
pub fn send_args<W>(writer: &mut W, service: u32, tag_bytes: &[u8], data: *const *const ())
|
||||||
-> Result<(), Error<T::WriteError>>
|
-> Result<(), Error<W::WriteError>>
|
||||||
where T: Write + ?Sized
|
where W: Write + ?Sized
|
||||||
{
|
{
|
||||||
let (arg_tags_bytes, return_tag_bytes) = split_tag(tag_bytes);
|
let (arg_tags_bytes, return_tag_bytes) = split_tag(tag_bytes);
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,59 @@
|
||||||
|
use core::str::Utf8Error;
|
||||||
use alloc::{Vec, String};
|
use alloc::{Vec, String};
|
||||||
|
|
||||||
use io::{Read, ProtoRead, Write, ProtoWrite, Error};
|
use io::{Read, ProtoRead, Write, ProtoWrite, Error as IoError, ReadStringError};
|
||||||
|
|
||||||
fn read_sync<T: Read + ?Sized>(reader: &mut T) -> Result<(), Error<T::ReadError>> {
|
#[derive(Fail, Debug)]
|
||||||
|
pub enum Error<T> {
|
||||||
|
#[fail(display = "incorrect magic")]
|
||||||
|
WrongMagic,
|
||||||
|
#[fail(display = "unknown packet {:#02x}", _0)]
|
||||||
|
UnknownPacket(u8),
|
||||||
|
#[fail(display = "invalid UTF-8: {}", _0)]
|
||||||
|
Utf8(Utf8Error),
|
||||||
|
#[fail(display = "{}", _0)]
|
||||||
|
Io(#[cause] IoError<T>)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<IoError<T>> for Error<T> {
|
||||||
|
fn from(value: IoError<T>) -> Error<T> {
|
||||||
|
Error::Io(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<ReadStringError<IoError<T>>> for Error<T> {
|
||||||
|
fn from(value: ReadStringError<IoError<T>>) -> Error<T> {
|
||||||
|
match value {
|
||||||
|
ReadStringError::Utf8(err) => Error::Utf8(err),
|
||||||
|
ReadStringError::Other(err) => Error::Io(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std_artiq")]
|
||||||
|
impl From<::std_artiq::io::Error> for Error<::std_artiq::io::Error> {
|
||||||
|
fn from(value: ::std_artiq::io::Error) -> Error<::std_artiq::io::Error> {
|
||||||
|
Error::Io(IoError::Other(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_magic<R>(reader: &mut R) -> Result<(), Error<R::ReadError>>
|
||||||
|
where R: Read + ?Sized
|
||||||
|
{
|
||||||
|
const MAGIC: &'static [u8] = b"ARTIQ coredev\n";
|
||||||
|
|
||||||
|
let mut magic: [u8; 14] = [0; 14];
|
||||||
|
reader.read_exact(&mut magic)?;
|
||||||
|
if magic != MAGIC {
|
||||||
|
Err(Error::WrongMagic)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_sync<R>(reader: &mut R) -> Result<(), IoError<R::ReadError>>
|
||||||
|
where R: Read + ?Sized
|
||||||
|
{
|
||||||
let mut sync = [0; 4];
|
let mut sync = [0; 4];
|
||||||
for i in 0.. {
|
for i in 0.. {
|
||||||
sync[i % 4] = reader.read_u8()?;
|
sync[i % 4] = reader.read_u8()?;
|
||||||
|
@ -11,7 +62,9 @@ fn read_sync<T: Read + ?Sized>(reader: &mut T) -> Result<(), Error<T::ReadError>
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_sync<T: Write + ?Sized>(writer: &mut T) -> Result<(), Error<T::WriteError>> {
|
fn write_sync<W>(writer: &mut W) -> Result<(), IoError<W::WriteError>>
|
||||||
|
where W: Write + ?Sized
|
||||||
|
{
|
||||||
writer.write_all(&[0x5a; 4])
|
writer.write_all(&[0x5a; 4])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +94,9 @@ pub enum Request {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Request {
|
impl Request {
|
||||||
pub fn read_from<T: Read + ?Sized>(reader: &mut T) -> Result<Self, Error<T::ReadError>> {
|
pub fn read_from<R>(reader: &mut R) -> Result<Self, Error<R::ReadError>>
|
||||||
|
where R: Read + ?Sized
|
||||||
|
{
|
||||||
read_sync(reader)?;
|
read_sync(reader)?;
|
||||||
Ok(match reader.read_u8()? {
|
Ok(match reader.read_u8()? {
|
||||||
3 => Request::SystemInfo,
|
3 => Request::SystemInfo,
|
||||||
|
@ -73,7 +128,7 @@ impl Request {
|
||||||
12 => Request::FlashRemove {
|
12 => Request::FlashRemove {
|
||||||
key: reader.read_string()?
|
key: reader.read_string()?
|
||||||
},
|
},
|
||||||
_ => return Err(Error::Unrecognized)
|
ty => return Err(Error::UnknownPacket(ty))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,7 +169,9 @@ pub enum Reply<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Reply<'a> {
|
impl<'a> Reply<'a> {
|
||||||
pub fn write_to<T: Write + ?Sized>(&self, writer: &mut T) -> Result<(), Error<T::WriteError>> {
|
pub fn write_to<W>(&self, writer: &mut W) -> Result<(), IoError<W::WriteError>>
|
||||||
|
where W: Write + ?Sized
|
||||||
|
{
|
||||||
write_sync(writer)?;
|
write_sync(writer)?;
|
||||||
match *self {
|
match *self {
|
||||||
Reply::SystemInfo { ident, finished_cleanly } => {
|
Reply::SystemInfo { ident, finished_cleanly } => {
|
||||||
|
|
|
@ -10,3 +10,6 @@ path = "lib.rs"
|
||||||
[features]
|
[features]
|
||||||
alloc = []
|
alloc = []
|
||||||
io_error_alloc = []
|
io_error_alloc = []
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
failure = { version = "0.1", default-features = false }
|
||||||
|
|
|
@ -8,6 +8,7 @@ extern crate std_unicode;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
#[macro_reexport(vec, format)]
|
#[macro_reexport(vec, format)]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
extern crate failure;
|
||||||
|
|
||||||
pub use core::{any, cell, clone, cmp, convert, default, hash, iter, marker, mem, num,
|
pub use core::{any, cell, clone, cmp, convert, default, hash, iter, marker, mem, num,
|
||||||
ops, option, ptr, result, sync,
|
ops, option, ptr, result, sync,
|
||||||
|
@ -38,3 +39,5 @@ impl<T> FakeBox<T> {
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl failure::Fail for error::Error + Send + Sync {}
|
||||||
|
|
|
@ -14,6 +14,8 @@ build_misoc = { path = "../libbuild_misoc" }
|
||||||
build_artiq = { path = "../libbuild_artiq" }
|
build_artiq = { path = "../libbuild_artiq" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
failure = { version = "0.1", default-features = false }
|
||||||
|
failure_derive = { version = "0.1", default-features = false }
|
||||||
byteorder = { version = "1.0", default-features = false }
|
byteorder = { version = "1.0", default-features = false }
|
||||||
cslice = { version = "0.3" }
|
cslice = { version = "0.3" }
|
||||||
log = { version = "0.4", default-features = false }
|
log = { version = "0.4", default-features = false }
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use io;
|
|
||||||
use kernel_proto as kern;
|
use kernel_proto as kern;
|
||||||
use sched::Io;
|
use sched::Io;
|
||||||
use session::{kern_acknowledge, kern_send};
|
use session::{kern_acknowledge, kern_send, Error};
|
||||||
#[cfg(has_rtio_core)]
|
#[cfg(has_rtio_core)]
|
||||||
use rtio_mgt;
|
use rtio_mgt;
|
||||||
|
|
||||||
|
@ -291,7 +290,7 @@ mod spi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_kern_hwreq(io: &Io, request: &kern::Message) -> Result<bool, io::Error<::std::io::Error>> {
|
pub fn process_kern_hwreq(io: &Io, request: &kern::Message) -> Result<bool, Error<::std::io::Error>> {
|
||||||
match request {
|
match request {
|
||||||
#[cfg(has_rtio_core)]
|
#[cfg(has_rtio_core)]
|
||||||
&kern::RtioInitRequest => {
|
&kern::RtioInitRequest => {
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
#![feature(lang_items, alloc, global_allocator, try_from, nonzero, nll)]
|
#![feature(lang_items, alloc, global_allocator, try_from, nonzero, nll)]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
extern crate failure;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate failure_derive;
|
||||||
extern crate cslice;
|
extern crate cslice;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
|
@ -1,27 +1,15 @@
|
||||||
use log::{self, LevelFilter};
|
use log::{self, LevelFilter};
|
||||||
|
|
||||||
use io::{self, Read, Write, ProtoWrite};
|
use io::{Write, ProtoWrite, Error as IoError};
|
||||||
use board_misoc::boot;
|
use board_misoc::boot;
|
||||||
use logger_artiq::BufferLogger;
|
use logger_artiq::BufferLogger;
|
||||||
|
use mgmt_proto::*;
|
||||||
use sched::Io;
|
use sched::Io;
|
||||||
use sched::{TcpListener, TcpStream};
|
use sched::{TcpListener, TcpStream};
|
||||||
use mgmt_proto::*;
|
|
||||||
use profiler;
|
use profiler;
|
||||||
|
|
||||||
fn check_magic(stream: &mut TcpStream) -> Result<(), io::Error<::std::io::Error>> {
|
fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), Error<::std::io::Error>> {
|
||||||
const MAGIC: &'static [u8] = b"ARTIQ management\n";
|
read_magic(stream)?;
|
||||||
|
|
||||||
let mut magic: [u8; 17] = [0; 17];
|
|
||||||
stream.read_exact(&mut magic)?;
|
|
||||||
if magic != MAGIC {
|
|
||||||
Err(io::Error::Unrecognized)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), io::Error<::std::io::Error>> {
|
|
||||||
check_magic(stream)?;
|
|
||||||
info!("new connection from {}", stream.remote_endpoint());
|
info!("new connection from {}", stream.remote_endpoint());
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -34,7 +22,7 @@ fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), io::Error<::std::io::Er
|
||||||
}
|
}
|
||||||
|
|
||||||
Request::ClearLog => {
|
Request::ClearLog => {
|
||||||
BufferLogger::with(|logger| -> Result<(), io::Error<::std::io::Error>> {
|
BufferLogger::with(|logger| -> Result<(), Error<::std::io::Error>> {
|
||||||
let mut buffer = io.until_ok(|| logger.buffer())?;
|
let mut buffer = io.until_ok(|| logger.buffer())?;
|
||||||
Ok(buffer.clear())
|
Ok(buffer.clear())
|
||||||
})?;
|
})?;
|
||||||
|
@ -43,7 +31,7 @@ fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), io::Error<::std::io::Er
|
||||||
}
|
}
|
||||||
|
|
||||||
Request::PullLog => {
|
Request::PullLog => {
|
||||||
BufferLogger::with(|logger| -> Result<(), io::Error<::std::io::Error>> {
|
BufferLogger::with(|logger| -> Result<(), Error<::std::io::Error>> {
|
||||||
loop {
|
loop {
|
||||||
// Do this *before* acquiring the buffer, since that sets the log level
|
// Do this *before* acquiring the buffer, since that sets the log level
|
||||||
// to OFF.
|
// to OFF.
|
||||||
|
@ -165,7 +153,7 @@ pub fn thread(io: Io) {
|
||||||
let mut stream = TcpStream::from_handle(&io, stream);
|
let mut stream = TcpStream::from_handle(&io, stream);
|
||||||
match worker(&io, &mut stream) {
|
match worker(&io, &mut stream) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(io::Error::UnexpectedEnd) => (),
|
Err(Error::Io(IoError::UnexpectedEnd)) => (),
|
||||||
Err(err) => error!("aborted: {}", err)
|
Err(err) => error!("aborted: {}", err)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,26 +1,12 @@
|
||||||
use alloc::btree_map::BTreeMap;
|
use alloc::btree_map::BTreeMap;
|
||||||
|
|
||||||
use io::{self, Read};
|
use moninj_proto::*;
|
||||||
use sched::Io;
|
use sched::Io;
|
||||||
use sched::{TcpListener, TcpStream};
|
use sched::{TcpListener, TcpStream};
|
||||||
use board_misoc::{clock, csr};
|
use board_misoc::{clock, csr};
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
use drtioaux;
|
use drtioaux;
|
||||||
|
|
||||||
use moninj_proto::*;
|
|
||||||
|
|
||||||
fn check_magic(stream: &mut TcpStream) -> Result<(), io::Error<::std::io::Error>> {
|
|
||||||
const MAGIC: &'static [u8] = b"ARTIQ moninj\n";
|
|
||||||
|
|
||||||
let mut magic: [u8; 13] = [0; 13];
|
|
||||||
stream.read_exact(&mut magic)?;
|
|
||||||
if magic != MAGIC {
|
|
||||||
Err(io::Error::Unrecognized)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(has_rtio_moninj)]
|
#[cfg(has_rtio_moninj)]
|
||||||
fn read_probe_local(channel: u16, probe: u8) -> u32 {
|
fn read_probe_local(channel: u16, probe: u8) -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -159,11 +145,11 @@ fn read_injection_status(channel: u32, probe: u8) -> u8 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn connection_worker(io: &Io, mut stream: &mut TcpStream) -> Result<(), io::Error<::std::io::Error>> {
|
fn connection_worker(io: &Io, mut stream: &mut TcpStream) -> Result<(), Error<::std::io::Error>> {
|
||||||
let mut watch_list = BTreeMap::new();
|
let mut watch_list = BTreeMap::new();
|
||||||
let mut next_check = 0;
|
let mut next_check = 0;
|
||||||
|
|
||||||
check_magic(&mut stream)?;
|
read_magic(&mut stream)?;
|
||||||
info!("new connection from {}", stream.remote_endpoint());
|
info!("new connection from {}", stream.remote_endpoint());
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use core::{mem, str, cell::{Cell, RefCell}, fmt::Write as FmtWrite};
|
||||||
use alloc::{Vec, String};
|
use alloc::{Vec, String};
|
||||||
use byteorder::{ByteOrder, NetworkEndian};
|
use byteorder::{ByteOrder, NetworkEndian};
|
||||||
|
|
||||||
use io::{self, Read, Write};
|
use io::{self, Read, Write, Error as IoError};
|
||||||
use board_misoc::{ident, cache, config};
|
use board_misoc::{ident, cache, config};
|
||||||
use {mailbox, rpc_queue, kernel};
|
use {mailbox, rpc_queue, kernel};
|
||||||
use urc::Urc;
|
use urc::Urc;
|
||||||
|
@ -19,17 +19,46 @@ use rpc_proto as rpc;
|
||||||
use session_proto as host;
|
use session_proto as host;
|
||||||
use kernel_proto as kern;
|
use kernel_proto as kern;
|
||||||
|
|
||||||
macro_rules! unexpected {
|
#[derive(Fail, Debug)]
|
||||||
($($arg:tt)*) => {
|
pub enum Error<T> {
|
||||||
{
|
#[fail(display = "cannot load kernel: {}", _0)]
|
||||||
error!($($arg)*);
|
Load(String),
|
||||||
return Err(io::Error::Unrecognized)
|
#[fail(display = "kernel not found")]
|
||||||
}
|
KernelNotFound,
|
||||||
};
|
#[fail(display = "invalid kernel CPU pointer: {:#08x}", _0)]
|
||||||
|
InvalidPointer(usize),
|
||||||
|
#[fail(display = "RTIO clock failure")]
|
||||||
|
ClockFailure,
|
||||||
|
#[fail(display = "watchdog {} expired", _0)]
|
||||||
|
WatchdogExpired(usize),
|
||||||
|
#[fail(display = "out of watchdogs")]
|
||||||
|
OutOfWatchdogs,
|
||||||
|
#[fail(display = "protocol error: {}", _0)]
|
||||||
|
Protocol(#[cause] host::Error<T>),
|
||||||
|
#[fail(display = "{}", _0)]
|
||||||
|
Unexpected(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn io_error(msg: &str) -> io::Error<::std::io::Error> {
|
impl<T> From<host::Error<T>> for Error<T> {
|
||||||
io::Error::Other(::std::io::Error::new(::std::io::ErrorKind::Other, msg))
|
fn from(value: host::Error<T>) -> Error<T> {
|
||||||
|
Error::Protocol(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<::std::io::Error> for Error<::std::io::Error> {
|
||||||
|
fn from(value: ::std::io::Error) -> Error<::std::io::Error> {
|
||||||
|
Error::Protocol(host::Error::Io(io::Error::Other(value)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error<::std::io::Error>> for Error<::std::io::Error> {
|
||||||
|
fn from(value: io::Error<::std::io::Error>) -> Error<::std::io::Error> {
|
||||||
|
Error::Protocol(host::Error::Io(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! unexpected {
|
||||||
|
($($arg:tt)*) => (return Err(Error::Unexpected(format!($($arg)*))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Persistent state
|
// Persistent state
|
||||||
|
@ -102,20 +131,10 @@ impl<'a> Drop for Session<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_magic(stream: &mut TcpStream) -> Result<(), io::Error<::std::io::Error>> {
|
fn host_read<R>(reader: &mut R) -> Result<host::Request, Error<R::ReadError>>
|
||||||
const MAGIC: &'static [u8] = b"ARTIQ coredev\n";
|
where R: Read + ?Sized
|
||||||
|
{
|
||||||
let mut magic: [u8; 14] = [0; 14];
|
let request = host::Request::read_from(reader)?;
|
||||||
stream.read_exact(&mut magic)?;
|
|
||||||
if magic != MAGIC {
|
|
||||||
Err(io::Error::Unrecognized)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn host_read(stream: &mut TcpStream) -> Result<host::Request, io::Error<::std::io::Error>> {
|
|
||||||
let request = host::Request::read_from(stream)?;
|
|
||||||
match &request {
|
match &request {
|
||||||
&host::Request::LoadKernel(_) => debug!("comm<-host LoadLibrary(...)"),
|
&host::Request::LoadKernel(_) => debug!("comm<-host LoadLibrary(...)"),
|
||||||
_ => debug!("comm<-host {:?}", request)
|
_ => debug!("comm<-host {:?}", request)
|
||||||
|
@ -123,12 +142,14 @@ fn host_read(stream: &mut TcpStream) -> Result<host::Request, io::Error<::std::i
|
||||||
Ok(request)
|
Ok(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn host_write(stream: &mut TcpStream, reply: host::Reply) -> Result<(), io::Error<::std::io::Error>> {
|
fn host_write<W>(writer: &mut W, reply: host::Reply) -> Result<(), IoError<W::WriteError>>
|
||||||
|
where W: Write + ?Sized
|
||||||
|
{
|
||||||
debug!("comm->host {:?}", reply);
|
debug!("comm->host {:?}", reply);
|
||||||
reply.write_to(stream)
|
reply.write_to(writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kern_send(io: &Io, request: &kern::Message) -> Result<(), io::Error<::std::io::Error>> {
|
pub fn kern_send(io: &Io, request: &kern::Message) -> Result<(), Error<::std::io::Error>> {
|
||||||
match request {
|
match request {
|
||||||
&kern::LoadRequest(_) => debug!("comm->kern LoadRequest(...)"),
|
&kern::LoadRequest(_) => debug!("comm->kern LoadRequest(...)"),
|
||||||
&kern::DmaRetrieveReply { trace, duration } => {
|
&kern::DmaRetrieveReply { trace, duration } => {
|
||||||
|
@ -144,12 +165,11 @@ pub fn kern_send(io: &Io, request: &kern::Message) -> Result<(), io::Error<::std
|
||||||
Ok(io.until(mailbox::acknowledged)?)
|
Ok(io.until(mailbox::acknowledged)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kern_recv_notrace<R, F>(io: &Io, f: F) -> Result<R, io::Error<::std::io::Error>>
|
fn kern_recv_notrace<R, F>(io: &Io, f: F) -> Result<R, Error<::std::io::Error>>
|
||||||
where F: FnOnce(&kern::Message) -> Result<R, io::Error<::std::io::Error>> {
|
where F: FnOnce(&kern::Message) -> Result<R, Error<::std::io::Error>> {
|
||||||
io.until(|| mailbox::receive() != 0)?;
|
io.until(|| mailbox::receive() != 0)?;
|
||||||
if !kernel::validate(mailbox::receive()) {
|
if !kernel::validate(mailbox::receive()) {
|
||||||
let message = format!("invalid kernel CPU pointer 0x{:x}", mailbox::receive());
|
return Err(Error::InvalidPointer(mailbox::receive()))
|
||||||
return Err(io::Error::Other(::std::io::Error::new(::std::io::ErrorKind::InvalidData, message)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
f(unsafe { &*(mailbox::receive() as *const kern::Message) })
|
f(unsafe { &*(mailbox::receive() as *const kern::Message) })
|
||||||
|
@ -171,20 +191,21 @@ fn kern_recv_dotrace(reply: &kern::Message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn kern_recv<R, F>(io: &Io, f: F) -> Result<R, io::Error<::std::io::Error>>
|
fn kern_recv<R, F>(io: &Io, f: F) -> Result<R, Error<::std::io::Error>>
|
||||||
where F: FnOnce(&kern::Message) -> Result<R, io::Error<::std::io::Error>> {
|
where F: FnOnce(&kern::Message) -> Result<R, Error<::std::io::Error>> {
|
||||||
kern_recv_notrace(io, |reply| {
|
kern_recv_notrace(io, |reply| {
|
||||||
kern_recv_dotrace(reply);
|
kern_recv_dotrace(reply);
|
||||||
f(reply)
|
f(reply)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kern_acknowledge() -> Result<(), io::Error<::std::io::Error>> {
|
pub fn kern_acknowledge() -> Result<(), Error<::std::io::Error>> {
|
||||||
mailbox::acknowledge();
|
mailbox::acknowledge();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn kern_load(io: &Io, session: &mut Session, library: &[u8]) -> Result<(), io::Error<::std::io::Error>> {
|
unsafe fn kern_load(io: &Io, session: &mut Session, library: &[u8])
|
||||||
|
-> Result<(), Error<::std::io::Error>> {
|
||||||
if session.running() {
|
if session.running() {
|
||||||
unexpected!("attempted to load a new kernel while a kernel was running")
|
unexpected!("attempted to load a new kernel while a kernel was running")
|
||||||
}
|
}
|
||||||
|
@ -194,14 +215,13 @@ unsafe fn kern_load(io: &Io, session: &mut Session, library: &[u8]) -> Result<()
|
||||||
kern_send(io, &kern::LoadRequest(&library))?;
|
kern_send(io, &kern::LoadRequest(&library))?;
|
||||||
kern_recv(io, |reply| {
|
kern_recv(io, |reply| {
|
||||||
match reply {
|
match reply {
|
||||||
&kern::LoadReply(Ok(())) => {
|
kern::LoadReply(Ok(())) => {
|
||||||
session.kernel_state = KernelState::Loaded;
|
session.kernel_state = KernelState::Loaded;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
&kern::LoadReply(Err(ref error)) => {
|
kern::LoadReply(Err(error)) => {
|
||||||
kernel::stop();
|
kernel::stop();
|
||||||
Err(io::Error::Other(::std::io::Error::new(::std::io::ErrorKind::Other,
|
Err(Error::Load(format!("{}", error)))
|
||||||
format!("cannot load kernel: {}", error))))
|
|
||||||
}
|
}
|
||||||
other =>
|
other =>
|
||||||
unexpected!("unexpected reply from kernel CPU: {:?}", other)
|
unexpected!("unexpected reply from kernel CPU: {:?}", other)
|
||||||
|
@ -209,7 +229,7 @@ unsafe fn kern_load(io: &Io, session: &mut Session, library: &[u8]) -> Result<()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kern_run(session: &mut Session) -> Result<(), io::Error<::std::io::Error>> {
|
fn kern_run(session: &mut Session) -> Result<(), Error<::std::io::Error>> {
|
||||||
if session.kernel_state != KernelState::Loaded {
|
if session.kernel_state != KernelState::Loaded {
|
||||||
unexpected!("attempted to run a kernel while not in Loaded state")
|
unexpected!("attempted to run a kernel while not in Loaded state")
|
||||||
}
|
}
|
||||||
|
@ -221,15 +241,14 @@ fn kern_run(session: &mut Session) -> Result<(), io::Error<::std::io::Error>> {
|
||||||
|
|
||||||
fn process_host_message(io: &Io,
|
fn process_host_message(io: &Io,
|
||||||
stream: &mut TcpStream,
|
stream: &mut TcpStream,
|
||||||
session: &mut Session) -> Result<(), io::Error<::std::io::Error>> {
|
session: &mut Session) -> Result<(), Error<::std::io::Error>> {
|
||||||
match host_read(stream)? {
|
match host_read(stream)? {
|
||||||
host::Request::SystemInfo => {
|
host::Request::SystemInfo => {
|
||||||
host_write(stream, host::Reply::SystemInfo {
|
host_write(stream, host::Reply::SystemInfo {
|
||||||
ident: ident::read(&mut [0; 64]),
|
ident: ident::read(&mut [0; 64]),
|
||||||
finished_cleanly: session.congress.finished_cleanly.get()
|
finished_cleanly: session.congress.finished_cleanly.get()
|
||||||
})?;
|
})?;
|
||||||
session.congress.finished_cleanly.set(true);
|
session.congress.finished_cleanly.set(true)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// artiq_coreconfig
|
// artiq_coreconfig
|
||||||
|
@ -239,29 +258,26 @@ fn process_host_message(io: &Io,
|
||||||
Ok(value) => host_write(stream, host::Reply::FlashRead(&value)),
|
Ok(value) => host_write(stream, host::Reply::FlashRead(&value)),
|
||||||
Err(_) => host_write(stream, host::Reply::FlashError)
|
Err(_) => host_write(stream, host::Reply::FlashError)
|
||||||
}
|
}
|
||||||
})
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
host::Request::FlashWrite { ref key, ref value } => {
|
host::Request::FlashWrite { ref key, ref value } => {
|
||||||
match config::write(key, value) {
|
match config::write(key, value) {
|
||||||
Ok(_) => host_write(stream, host::Reply::FlashOk),
|
Ok(_) => host_write(stream, host::Reply::FlashOk),
|
||||||
Err(_) => host_write(stream, host::Reply::FlashError)
|
Err(_) => host_write(stream, host::Reply::FlashError)
|
||||||
}
|
}?;
|
||||||
}
|
}
|
||||||
|
|
||||||
host::Request::FlashRemove { ref key } => {
|
host::Request::FlashRemove { ref key } => {
|
||||||
match config::remove(key) {
|
match config::remove(key) {
|
||||||
Ok(()) => host_write(stream, host::Reply::FlashOk),
|
Ok(()) => host_write(stream, host::Reply::FlashOk),
|
||||||
Err(_) => host_write(stream, host::Reply::FlashError),
|
Err(_) => host_write(stream, host::Reply::FlashError),
|
||||||
}
|
}?;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
host::Request::FlashErase => {
|
host::Request::FlashErase => {
|
||||||
match config::erase() {
|
match config::erase() {
|
||||||
Ok(()) => host_write(stream, host::Reply::FlashOk),
|
Ok(()) => host_write(stream, host::Reply::FlashOk),
|
||||||
Err(_) => host_write(stream, host::Reply::FlashError),
|
Err(_) => host_write(stream, host::Reply::FlashError),
|
||||||
}
|
}?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// artiq_run/artiq_master
|
// artiq_run/artiq_master
|
||||||
|
@ -273,9 +289,9 @@ fn process_host_message(io: &Io,
|
||||||
#[cfg(has_rtio_core)]
|
#[cfg(has_rtio_core)]
|
||||||
{
|
{
|
||||||
if rtio_mgt::crg::switch_clock(clk) {
|
if rtio_mgt::crg::switch_clock(clk) {
|
||||||
host_write(stream, host::Reply::ClockSwitchCompleted)
|
host_write(stream, host::Reply::ClockSwitchCompleted)?;
|
||||||
} else {
|
} else {
|
||||||
host_write(stream, host::Reply::ClockSwitchFailed)
|
host_write(stream, host::Reply::ClockSwitchFailed)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,19 +301,18 @@ fn process_host_message(io: &Io,
|
||||||
|
|
||||||
host::Request::LoadKernel(kernel) =>
|
host::Request::LoadKernel(kernel) =>
|
||||||
match unsafe { kern_load(io, session, &kernel) } {
|
match unsafe { kern_load(io, session, &kernel) } {
|
||||||
Ok(()) => host_write(stream, host::Reply::LoadCompleted),
|
Ok(()) => host_write(stream, host::Reply::LoadCompleted)?,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let mut description = String::new();
|
let mut description = String::new();
|
||||||
write!(&mut description, "{}", error).unwrap();
|
write!(&mut description, "{}", error).unwrap();
|
||||||
host_write(stream, host::Reply::LoadFailed(&description))?;
|
host_write(stream, host::Reply::LoadFailed(&description))?;
|
||||||
kern_acknowledge()
|
kern_acknowledge()?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
host::Request::RunKernel =>
|
host::Request::RunKernel =>
|
||||||
match kern_run(session) {
|
match kern_run(session) {
|
||||||
Ok(()) => Ok(()),
|
Ok(()) => (),
|
||||||
Err(_) => host_write(stream, host::Reply::KernelStartupFailed)
|
Err(_) => host_write(stream, host::Reply::KernelStartupFailed)?
|
||||||
},
|
},
|
||||||
|
|
||||||
host::Request::RpcReply { tag } => {
|
host::Request::RpcReply { tag } => {
|
||||||
|
@ -311,7 +326,7 @@ fn process_host_message(io: &Io,
|
||||||
other => unexpected!("unexpected reply from kernel CPU: {:?}", other)
|
other => unexpected!("unexpected reply from kernel CPU: {:?}", other)
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
rpc::recv_return(stream, &tag, slot, &|size| {
|
rpc::recv_return(stream, &tag, slot, &|size| -> Result<_, Error<::std::io::Error>> {
|
||||||
kern_send(io, &kern::RpcRecvReply(Ok(size)))?;
|
kern_send(io, &kern::RpcRecvReply(Ok(size)))?;
|
||||||
Ok(kern_recv(io, |reply| {
|
Ok(kern_recv(io, |reply| {
|
||||||
match reply {
|
match reply {
|
||||||
|
@ -322,8 +337,7 @@ fn process_host_message(io: &Io,
|
||||||
})?;
|
})?;
|
||||||
kern_send(io, &kern::RpcRecvReply(Ok(0)))?;
|
kern_send(io, &kern::RpcRecvReply(Ok(0)))?;
|
||||||
|
|
||||||
session.kernel_state = KernelState::Running;
|
session.kernel_state = KernelState::Running
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
host::Request::RpcException {
|
host::Request::RpcException {
|
||||||
|
@ -352,14 +366,15 @@ fn process_host_message(io: &Io,
|
||||||
};
|
};
|
||||||
kern_send(io, &kern::RpcRecvReply(Err(exn)))?;
|
kern_send(io, &kern::RpcRecvReply(Err(exn)))?;
|
||||||
|
|
||||||
session.kernel_state = KernelState::Running;
|
session.kernel_state = KernelState::Running
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>,
|
fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>,
|
||||||
session: &mut Session) -> Result<bool, io::Error<::std::io::Error>> {
|
session: &mut Session) -> Result<bool, Error<::std::io::Error>> {
|
||||||
kern_recv_notrace(io, |request| {
|
kern_recv_notrace(io, |request| {
|
||||||
match (request, session.kernel_state) {
|
match (request, session.kernel_state) {
|
||||||
(&kern::LoadReply(_), KernelState::Loaded) |
|
(&kern::LoadReply(_), KernelState::Loaded) |
|
||||||
|
@ -383,8 +398,9 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>,
|
||||||
match request {
|
match request {
|
||||||
&kern::Log(args) => {
|
&kern::Log(args) => {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
session.log_buffer.write_fmt(args)
|
session.log_buffer
|
||||||
.map_err(|_| io_error("cannot append to session log buffer"))?;
|
.write_fmt(args)
|
||||||
|
.unwrap_or_else(|_| warn!("cannot append to session log buffer"));
|
||||||
session.flush_log_buffer();
|
session.flush_log_buffer();
|
||||||
kern_acknowledge()
|
kern_acknowledge()
|
||||||
}
|
}
|
||||||
|
@ -430,11 +446,9 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>,
|
||||||
}
|
}
|
||||||
|
|
||||||
&kern::WatchdogSetRequest { ms } => {
|
&kern::WatchdogSetRequest { ms } => {
|
||||||
let id = session.watchdog_set.set_ms(ms)
|
let id = session.watchdog_set.set_ms(ms).map_err(|()| Error::OutOfWatchdogs)?;
|
||||||
.map_err(|()| io_error("out of watchdogs"))?;
|
|
||||||
kern_send(io, &kern::WatchdogSetReply { id: id })
|
kern_send(io, &kern::WatchdogSetReply { id: id })
|
||||||
}
|
}
|
||||||
|
|
||||||
&kern::WatchdogClear { id } => {
|
&kern::WatchdogClear { id } => {
|
||||||
session.watchdog_set.clear(id);
|
session.watchdog_set.clear(id);
|
||||||
kern_acknowledge()
|
kern_acknowledge()
|
||||||
|
@ -476,10 +490,9 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>,
|
||||||
match stream {
|
match stream {
|
||||||
None => return Ok(true),
|
None => return Ok(true),
|
||||||
Some(ref mut stream) =>
|
Some(ref mut stream) =>
|
||||||
host_write(stream, host::Reply::KernelFinished)
|
host_write(stream, host::Reply::KernelFinished).map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&kern::RunException {
|
&kern::RunException {
|
||||||
exception: kern::Exception { name, message, param, file, line, column, function },
|
exception: kern::Exception { name, message, param, file, line, column, function },
|
||||||
backtrace
|
backtrace
|
||||||
|
@ -505,7 +518,7 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>,
|
||||||
column: column,
|
column: column,
|
||||||
function: function,
|
function: function,
|
||||||
backtrace: backtrace
|
backtrace: backtrace
|
||||||
})
|
}).map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -516,7 +529,7 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_kern_queued_rpc(stream: &mut TcpStream,
|
fn process_kern_queued_rpc(stream: &mut TcpStream,
|
||||||
_session: &mut Session) -> Result<(), io::Error<::std::io::Error>> {
|
_session: &mut Session) -> Result<(), Error<::std::io::Error>> {
|
||||||
rpc_queue::dequeue(|slice| {
|
rpc_queue::dequeue(|slice| {
|
||||||
debug!("comm<-kern (async RPC)");
|
debug!("comm<-kern (async RPC)");
|
||||||
let length = NetworkEndian::read_u32(slice) as usize;
|
let length = NetworkEndian::read_u32(slice) as usize;
|
||||||
|
@ -529,7 +542,7 @@ fn process_kern_queued_rpc(stream: &mut TcpStream,
|
||||||
|
|
||||||
fn host_kernel_worker(io: &Io,
|
fn host_kernel_worker(io: &Io,
|
||||||
stream: &mut TcpStream,
|
stream: &mut TcpStream,
|
||||||
congress: &mut Congress) -> Result<(), io::Error<::std::io::Error>> {
|
congress: &mut Congress) -> Result<(), Error<::std::io::Error>> {
|
||||||
let mut session = Session::new(congress);
|
let mut session = Session::new(congress);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -548,16 +561,16 @@ fn host_kernel_worker(io: &Io,
|
||||||
}
|
}
|
||||||
|
|
||||||
if session.kernel_state == KernelState::Running {
|
if session.kernel_state == KernelState::Running {
|
||||||
if session.watchdog_set.expired() {
|
if let Some(idx) = session.watchdog_set.expired() {
|
||||||
host_write(stream, host::Reply::WatchdogExpired)?;
|
host_write(stream, host::Reply::WatchdogExpired)?;
|
||||||
return Err(io_error("watchdog expired"))
|
return Err(Error::WatchdogExpired(idx))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(has_rtio_core)]
|
#[cfg(has_rtio_core)]
|
||||||
{
|
{
|
||||||
if !rtio_mgt::crg::check() {
|
if !rtio_mgt::crg::check() {
|
||||||
host_write(stream, host::Reply::ClockFailure)?;
|
host_write(stream, host::Reply::ClockFailure)?;
|
||||||
return Err(io_error("RTIO clock failure"))
|
return Err(Error::ClockFailure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -568,7 +581,7 @@ fn host_kernel_worker(io: &Io,
|
||||||
|
|
||||||
fn flash_kernel_worker(io: &Io,
|
fn flash_kernel_worker(io: &Io,
|
||||||
congress: &mut Congress,
|
congress: &mut Congress,
|
||||||
config_key: &str) -> Result<(), io::Error<::std::io::Error>> {
|
config_key: &str) -> Result<(), Error<::std::io::Error>> {
|
||||||
let mut session = Session::new(congress);
|
let mut session = Session::new(congress);
|
||||||
|
|
||||||
config::read(config_key, |result| {
|
config::read(config_key, |result| {
|
||||||
|
@ -578,15 +591,14 @@ fn flash_kernel_worker(io: &Io,
|
||||||
// so make a copy.
|
// so make a copy.
|
||||||
kern_load(io, &mut session, Vec::from(kernel).as_ref())
|
kern_load(io, &mut session, Vec::from(kernel).as_ref())
|
||||||
},
|
},
|
||||||
_ => Err(io::Error::Other(::std::io::Error::new(::std::io::ErrorKind::NotFound,
|
_ => Err(Error::KernelNotFound)
|
||||||
"kernel not found"))),
|
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
kern_run(&mut session)?;
|
kern_run(&mut session)?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if !rpc_queue::empty() {
|
if !rpc_queue::empty() {
|
||||||
return Err(io_error("unexpected background RPC in flash kernel"))
|
unexpected!("unexpected background RPC in flash kernel")
|
||||||
}
|
}
|
||||||
|
|
||||||
if mailbox::receive() != 0 {
|
if mailbox::receive() != 0 {
|
||||||
|
@ -595,14 +607,14 @@ fn flash_kernel_worker(io: &Io,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if session.watchdog_set.expired() {
|
if let Some(idx) = session.watchdog_set.expired() {
|
||||||
return Err(io_error("watchdog expired"))
|
return Err(Error::WatchdogExpired(idx))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(has_rtio_core)]
|
#[cfg(has_rtio_core)]
|
||||||
{
|
{
|
||||||
if !rtio_mgt::crg::check() {
|
if !rtio_mgt::crg::check() {
|
||||||
return Err(io_error("RTIO clock failure"))
|
return Err(Error::ClockFailure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,10 +651,10 @@ pub fn thread(io: Io) {
|
||||||
let mut congress = congress.borrow_mut();
|
let mut congress = congress.borrow_mut();
|
||||||
info!("running startup kernel");
|
info!("running startup kernel");
|
||||||
match flash_kernel_worker(&io, &mut congress, "startup_kernel") {
|
match flash_kernel_worker(&io, &mut congress, "startup_kernel") {
|
||||||
Ok(()) => info!("startup kernel finished"),
|
Ok(()) =>
|
||||||
Err(io::Error::Other(ref err)) if err.kind() == ::std::io::ErrorKind::NotFound => {
|
info!("startup kernel finished"),
|
||||||
info!("no startup kernel found")
|
Err(Error::KernelNotFound) =>
|
||||||
}
|
info!("no startup kernel found"),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
congress.finished_cleanly.set(false);
|
congress.finished_cleanly.set(false);
|
||||||
error!("startup kernel aborted: {}", err);
|
error!("startup kernel aborted: {}", err);
|
||||||
|
@ -657,7 +669,7 @@ pub fn thread(io: Io) {
|
||||||
stream.set_timeout(Some(1000));
|
stream.set_timeout(Some(1000));
|
||||||
stream.set_keep_alive(Some(500));
|
stream.set_keep_alive(Some(500));
|
||||||
|
|
||||||
match check_magic(&mut stream) {
|
match host::read_magic(&mut stream) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
warn!("wrong magic from {}", stream.remote_endpoint());
|
warn!("wrong magic from {}", stream.remote_endpoint());
|
||||||
|
@ -674,13 +686,11 @@ pub fn thread(io: Io) {
|
||||||
let mut stream = TcpStream::from_handle(&io, stream);
|
let mut stream = TcpStream::from_handle(&io, stream);
|
||||||
match host_kernel_worker(&io, &mut stream, &mut *congress) {
|
match host_kernel_worker(&io, &mut stream, &mut *congress) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(io::Error::UnexpectedEnd) => {
|
Err(Error::Protocol(host::Error::Io(io::Error::UnexpectedEnd))) =>
|
||||||
info!("connection closed");
|
info!("connection closed"),
|
||||||
}
|
Err(Error::Protocol(host::Error::Io(io::Error::Other(ref err))))
|
||||||
Err(io::Error::Other(ref err))
|
if err.kind() == ::std::io::ErrorKind::Interrupted =>
|
||||||
if err.kind() == ::std::io::ErrorKind::Interrupted => {
|
info!("kernel interrupted"),
|
||||||
info!("kernel interrupted");
|
|
||||||
}
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
congress.finished_cleanly.set(false);
|
congress.finished_cleanly.set(false);
|
||||||
error!("session aborted: {}", err);
|
error!("session aborted: {}", err);
|
||||||
|
@ -698,18 +708,16 @@ pub fn thread(io: Io) {
|
||||||
match flash_kernel_worker(&io, &mut *congress, "idle_kernel") {
|
match flash_kernel_worker(&io, &mut *congress, "idle_kernel") {
|
||||||
Ok(()) =>
|
Ok(()) =>
|
||||||
info!("idle kernel finished, standing by"),
|
info!("idle kernel finished, standing by"),
|
||||||
Err(io::Error::Other(ref err))
|
Err(Error::Protocol(host::Error::Io(io::Error::Other(ref err))))
|
||||||
if err.kind() == ::std::io::ErrorKind::Interrupted => {
|
if err.kind() == ::std::io::ErrorKind::Interrupted => {
|
||||||
info!("idle kernel interrupted");
|
info!("idle kernel interrupted");
|
||||||
}
|
}
|
||||||
Err(io::Error::Other(ref err))
|
Err(Error::KernelNotFound) => {
|
||||||
if err.kind() == ::std::io::ErrorKind::NotFound => {
|
|
||||||
info!("no idle kernel found");
|
info!("no idle kernel found");
|
||||||
while io.relinquish().is_ok() {}
|
while io.relinquish().is_ok() {}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) =>
|
||||||
error!("idle kernel aborted: {}", err);
|
error!("idle kernel aborted: {}", err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,10 +38,12 @@ impl WatchdogSet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expired(&self) -> bool {
|
pub fn expired(&self) -> Option<usize> {
|
||||||
self.watchdogs.iter()
|
self.watchdogs
|
||||||
.filter(|wd| wd.active)
|
.iter()
|
||||||
.min_by_key(|wd| wd.threshold)
|
.enumerate()
|
||||||
.map_or(false, |wd| clock::get_ms() > wd.threshold)
|
.filter(|(_, wd)| wd.active && clock::get_ms() > wd.threshold)
|
||||||
|
.min_by_key(|(_, wd)| wd.threshold)
|
||||||
|
.map_or(None, |(i, _)| Some(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue