firmware: eliminate uses of std_artiq::io::{Read,Write} from runtime.

This commit is contained in:
whitequark 2018-05-14 19:06:54 +00:00
parent cf33ba748d
commit 5ead27f2e1
12 changed files with 118 additions and 132 deletions

View File

@ -111,7 +111,6 @@ name = "io"
version = "0.0.0"
dependencies = [
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"std_artiq 0.0.0",
]
[[package]]

View File

@ -9,7 +9,6 @@ path = "lib.rs"
[dependencies]
byteorder = { version = "1.0", default-features = false, optional = true }
std_artiq = { path = "../libstd_artiq", optional = true }
[features]
alloc = []

View File

@ -8,9 +8,6 @@ extern crate alloc;
#[cfg(feature = "byteorder")]
extern crate byteorder;
#[cfg(feature = "std_artiq")]
extern crate std_artiq;
use core::result;
use core::fmt;
@ -67,6 +64,14 @@ pub trait Read {
}
}
impl<'a, T: Read> Read for &'a mut T {
type ReadError = T::ReadError;
fn read(&mut self, buf: &mut [u8]) -> result::Result<usize, Self::ReadError> {
T::read(self, buf)
}
}
pub trait Write {
type WriteError;
type FlushError;
@ -99,7 +104,23 @@ pub trait Write {
fn size_hint(&mut self, _min: usize, _max: Option<usize>) {}
}
#[cfg(not(feature = "std_artiq"))]
impl<'a, T: Write> Write for &'a mut T {
type WriteError = T::WriteError;
type FlushError = T::FlushError;
fn write(&mut self, buf: &[u8]) -> result::Result<usize, Self::WriteError> {
T::write(self, buf)
}
fn flush(&mut self) -> result::Result<(), Self::FlushError> {
T::flush(self)
}
fn size_hint(&mut self, min: usize, max: Option<usize>) {
T::size_hint(self, min, max)
}
}
impl<'a> Write for &'a mut [u8] {
type WriteError = !;
type FlushError = !;
@ -116,6 +137,22 @@ impl<'a> Write for &'a mut [u8] {
}
}
#[cfg(feature = "alloc")]
impl<'a> Write for alloc::Vec<u8> {
type WriteError = !;
type FlushError = !;
fn write(&mut self, buf: &[u8]) -> result::Result<usize, Self::WriteError> {
self.extend_from_slice(buf);
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> result::Result<(), Self::FlushError> {
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CursorError {
EndOfBuffer
@ -196,7 +233,7 @@ impl Write for Cursor<::alloc::Vec<u8>> {
#[inline]
fn write(&mut self, buf: &[u8]) -> result::Result<usize, Self::WriteError> {
self.inner.extend(buf);
self.inner.extend_from_slice(buf);
Ok(buf.len())
}
@ -205,44 +242,3 @@ impl Write for Cursor<::alloc::Vec<u8>> {
Ok(())
}
}
#[cfg(feature = "std_artiq")]
impl<T> Read for T where T: std_artiq::io::Read + ?Sized {
type ReadError = std_artiq::io::Error;
fn read(&mut self, buf: &mut [u8]) -> result::Result<usize, Self::ReadError> {
std_artiq::io::Read::read(self, buf)
}
}
#[cfg(feature = "std_artiq")]
impl<T> Write for T where T: std_artiq::io::Write + ?Sized {
type WriteError = std_artiq::io::Error;
type FlushError = std_artiq::io::Error;
fn write(&mut self, buf: &[u8]) -> result::Result<usize, Self::WriteError> {
std_artiq::io::Write::write(self, buf)
}
fn flush(&mut self) -> result::Result<(), Self::WriteError> {
std_artiq::io::Write::flush(self)
}
}
#[cfg(feature = "std_artiq")]
impl<T> From<Error<T>> for std_artiq::io::Error
where T: Into<std_artiq::io::Error>
{
fn from(value: Error<T>) -> std_artiq::io::Error {
match value {
Error::UnexpectedEof =>
std_artiq::io::Error::new(std_artiq::io::ErrorKind::UnexpectedEof,
"unexpected end of stream"),
Error::Unrecognized =>
std_artiq::io::Error::new(std_artiq::io::ErrorKind::InvalidData,
"unrecognized data"),
Error::Other(err) =>
err.into()
}
}
}

View File

@ -36,21 +36,6 @@ impl<T> From<ReadStringError<IoError<T>>> for IoError<T>
}
}
#[cfg(feature = "alloc")]
#[cfg(feature = "std_artiq")]
impl<T> From<ReadStringError<T>> for ::std_artiq::io::Error
where T: Into<::std_artiq::io::Error>
{
fn from(value: ReadStringError<T>) -> ::std_artiq::io::Error {
match value {
ReadStringError::Utf8Error(_) =>
::std_artiq::io::Error::new(::std_artiq::io::ErrorKind::InvalidData,
"invalid UTF-8"),
ReadStringError::Other(err) => err.into()
}
}
}
pub trait ProtoRead {
type ReadError;

View File

@ -19,7 +19,7 @@ cslice = { version = "0.3" }
log = { version = "0.4", default-features = false }
managed = { version = "0.6", default-features = false, features = ["alloc", "map"] }
unwind_backtrace = { path = "../libunwind_backtrace" }
io = { path = "../libio", features = ["byteorder", "std_artiq"] }
io = { path = "../libio", features = ["byteorder"] }
alloc_list = { path = "../liballoc_list" }
board_misoc = { path = "../libboard_misoc", features = ["uart_console", "smoltcp"] }
std_artiq = { path = "../libstd_artiq", features = ["alloc", "io_error_alloc"] }

View File

@ -1,4 +1,4 @@
use std::io::{self, Write};
use io::{self, Write};
use board_misoc::{csr, cache};
use sched::{Io, TcpListener, TcpStream};
use analyzer_proto::*;
@ -35,7 +35,7 @@ fn disarm() {
}
}
fn worker(stream: &mut TcpStream) -> io::Result<()> {
fn worker(stream: &mut TcpStream) -> io::Result<(), ::std::io::Error> {
let data = unsafe { &BUFFER.data[..] };
let overflow_occurred = unsafe { csr::rtio_analyzer::message_encoder_overflow_read() != 0 };
let total_byte_count = unsafe { csr::rtio_analyzer::dma_byte_count_read() };

View File

@ -1,4 +1,4 @@
use std::io;
use io;
use kernel_proto as kern;
use sched::Io;
use session::{kern_acknowledge, kern_send};
@ -291,7 +291,7 @@ mod spi {
}
}
pub fn process_kern_hwreq(io: &Io, request: &kern::Message) -> io::Result<bool> {
pub fn process_kern_hwreq(io: &Io, request: &kern::Message) -> io::Result<bool, ::std::io::Error> {
match request {
#[cfg(has_rtio_core)]
&kern::RtioInitRequest => {

View File

@ -1,27 +1,26 @@
use std::io::{self, Read, Write};
use log::{self, LevelFilter};
use io::{self, Read, Write, proto::ProtoWrite};
use board_misoc::boot;
use io::proto::ProtoWrite;
use logger_artiq::BufferLogger;
use sched::Io;
use sched::{TcpListener, TcpStream};
use mgmt_proto::*;
use profiler;
fn check_magic(stream: &mut TcpStream) -> io::Result<()> {
fn check_magic(stream: &mut TcpStream) -> io::Result<(), ::std::io::Error> {
const MAGIC: &'static [u8] = b"ARTIQ management\n";
let mut magic: [u8; 17] = [0; 17];
stream.read_exact(&mut magic)?;
if magic != MAGIC {
Err(io::Error::new(io::ErrorKind::InvalidData, "unrecognized magic"))
Err(io::Error::Unrecognized)
} else {
Ok(())
}
}
fn worker(io: &Io, stream: &mut TcpStream) -> io::Result<()> {
fn worker(io: &Io, stream: &mut TcpStream) -> io::Result<(), ::std::io::Error> {
check_magic(stream)?;
info!("new connection from {}", stream.remote_endpoint());
@ -35,7 +34,7 @@ fn worker(io: &Io, stream: &mut TcpStream) -> io::Result<()> {
}
Request::ClearLog => {
BufferLogger::with(|logger| -> io::Result<()> {
BufferLogger::with(|logger| -> io::Result<(), ::std::io::Error> {
let mut buffer = io.until_ok(|| logger.buffer())?;
Ok(buffer.clear())
})?;
@ -44,7 +43,7 @@ fn worker(io: &Io, stream: &mut TcpStream) -> io::Result<()> {
}
Request::PullLog => {
BufferLogger::with(|logger| -> io::Result<()> {
BufferLogger::with(|logger| -> io::Result<(), ::std::io::Error> {
loop {
// Do this *before* acquiring the buffer, since that sets the log level
// to OFF.
@ -166,8 +165,7 @@ pub fn thread(io: Io) {
let mut stream = TcpStream::from_handle(&io, stream);
match worker(&io, &mut stream) {
Ok(()) => (),
Err(ref err) if err.kind() == io::ErrorKind::UnexpectedEof => (),
Err(ref err) if err.kind() == io::ErrorKind::WriteZero => (),
Err(io::Error::UnexpectedEof) => (),
Err(err) => error!("aborted: {}", err)
}
});

View File

@ -1,6 +1,6 @@
use alloc::btree_map::BTreeMap;
use std::io::{self, Read};
use io::{self, Read};
use sched::Io;
use sched::{TcpListener, TcpStream};
use board_misoc::{clock, csr};
@ -9,13 +9,13 @@ use drtioaux;
use moninj_proto::*;
fn check_magic(stream: &mut TcpStream) -> io::Result<()> {
fn check_magic(stream: &mut TcpStream) -> io::Result<(), ::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::new(io::ErrorKind::InvalidData, "unrecognized magic"))
Err(io::Error::Unrecognized)
} else {
Ok(())
}
@ -159,7 +159,7 @@ fn read_injection_status(channel: u32, probe: u8) -> u8 {
0
}
fn connection_worker(io: &Io, mut stream: &mut TcpStream) -> io::Result<()> {
fn connection_worker(io: &Io, mut stream: &mut TcpStream) -> io::Result<(), ::std::io::Error> {
let mut watch_list = BTreeMap::new();
let mut next_check = 0;

View File

@ -1,7 +1,7 @@
use core::mem;
use alloc::{Vec, String, BTreeMap};
use std::io::Write;
use io::Write;
const ALIGNMENT: usize = 64;

View File

@ -9,8 +9,9 @@ use fringe::generator::{Generator, Yielder, State as GeneratorState};
use smoltcp::wire::IpEndpoint;
use smoltcp::socket::{SocketHandle, SocketRef};
use io::{Read, Write};
use board_misoc::clock;
use std::io::{Read, Write, Result, Error, ErrorKind};
use std::io::{Result, Error, ErrorKind};
use urc::Urc;
type SocketSet = ::smoltcp::socket::SocketSet<'static, 'static, 'static>;
@ -446,6 +447,8 @@ impl<'a> TcpStream<'a> {
}
impl<'a> Read for TcpStream<'a> {
type ReadError = Error;
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
// Only borrow the underlying socket for the span of the next statement.
let result = self.with_lower(|mut s| s.recv_slice(buf));
@ -470,6 +473,9 @@ impl<'a> Read for TcpStream<'a> {
}
impl<'a> Write for TcpStream<'a> {
type WriteError = Error;
type FlushError = Error;
fn write(&mut self, buf: &[u8]) -> Result<usize> {
// Only borrow the underlying socket for the span of the next statement.
let result = self.with_lower(|mut s| s.send_slice(buf));

View File

@ -2,8 +2,8 @@ use core::{mem, str, cell::{Cell, RefCell}, fmt::Write as FmtWrite};
use alloc::{Vec, String};
use byteorder::{ByteOrder, NetworkEndian};
use io::{self, Read, Write};
use board_misoc::{ident, cache, config};
use std::io::{self, Read, Write};
use {mailbox, rpc_queue, kernel};
use urc::Urc;
use sched::{ThreadHandle, Io};
@ -23,13 +23,13 @@ macro_rules! unexpected {
($($arg:tt)*) => {
{
error!($($arg)*);
return Err(io::Error::new(io::ErrorKind::InvalidData, "protocol error"))
return Err(io::Error::Unrecognized)
}
};
}
fn io_error(msg: &str) -> io::Error {
io::Error::new(io::ErrorKind::Other, msg)
fn io_error(msg: &str) -> io::Error<::std::io::Error> {
io::Error::Other(::std::io::Error::new(::std::io::ErrorKind::Other, msg))
}
// Persistent state
@ -102,19 +102,19 @@ impl<'a> Drop for Session<'a> {
}
}
fn check_magic(stream: &mut TcpStream) -> io::Result<()> {
fn check_magic(stream: &mut TcpStream) -> io::Result<(), ::std::io::Error> {
const MAGIC: &'static [u8] = b"ARTIQ coredev\n";
let mut magic: [u8; 14] = [0; 14];
stream.read_exact(&mut magic)?;
if magic != MAGIC {
Err(io::Error::new(io::ErrorKind::InvalidData, "unrecognized magic"))
Err(io::Error::Unrecognized)
} else {
Ok(())
}
}
fn host_read(stream: &mut TcpStream) -> io::Result<host::Request> {
fn host_read(stream: &mut TcpStream) -> io::Result<host::Request, ::std::io::Error> {
let request = host::Request::read_from(stream)?;
match &request {
&host::Request::LoadKernel(_) => debug!("comm<-host LoadLibrary(...)"),
@ -123,12 +123,12 @@ fn host_read(stream: &mut TcpStream) -> io::Result<host::Request> {
Ok(request)
}
fn host_write(stream: &mut Write, reply: host::Reply) -> io::Result<()> {
fn host_write(stream: &mut TcpStream, reply: host::Reply) -> io::Result<(), ::std::io::Error> {
debug!("comm->host {:?}", reply);
Ok(reply.write_to(stream)?)
reply.write_to(stream)
}
pub fn kern_send(io: &Io, request: &kern::Message) -> io::Result<()> {
pub fn kern_send(io: &Io, request: &kern::Message) -> io::Result<(), ::std::io::Error> {
match request {
&kern::LoadRequest(_) => debug!("comm->kern LoadRequest(...)"),
&kern::DmaRetrieveReply { trace, duration } => {
@ -141,15 +141,15 @@ pub fn kern_send(io: &Io, request: &kern::Message) -> io::Result<()> {
_ => debug!("comm->kern {:?}", request)
}
unsafe { mailbox::send(request as *const _ as usize) }
io.until(mailbox::acknowledged)
Ok(io.until(mailbox::acknowledged)?)
}
fn kern_recv_notrace<R, F>(io: &Io, f: F) -> io::Result<R>
where F: FnOnce(&kern::Message) -> io::Result<R> {
fn kern_recv_notrace<R, F>(io: &Io, f: F) -> io::Result<R, ::std::io::Error>
where F: FnOnce(&kern::Message) -> io::Result<R, ::std::io::Error> {
io.until(|| mailbox::receive() != 0)?;
if !kernel::validate(mailbox::receive()) {
let message = format!("invalid kernel CPU pointer 0x{:x}", mailbox::receive());
return Err(io::Error::new(io::ErrorKind::InvalidData, message))
return Err(io::Error::Other(::std::io::Error::new(::std::io::ErrorKind::InvalidData, message)))
}
f(unsafe { &*(mailbox::receive() as *const kern::Message) })
@ -171,20 +171,20 @@ fn kern_recv_dotrace(reply: &kern::Message) {
}
#[inline(always)]
fn kern_recv<R, F>(io: &Io, f: F) -> io::Result<R>
where F: FnOnce(&kern::Message) -> io::Result<R> {
fn kern_recv<R, F>(io: &Io, f: F) -> io::Result<R, ::std::io::Error>
where F: FnOnce(&kern::Message) -> io::Result<R, ::std::io::Error> {
kern_recv_notrace(io, |reply| {
kern_recv_dotrace(reply);
f(reply)
})
}
pub fn kern_acknowledge() -> io::Result<()> {
pub fn kern_acknowledge() -> io::Result<(), ::std::io::Error> {
mailbox::acknowledge();
Ok(())
}
unsafe fn kern_load(io: &Io, session: &mut Session, library: &[u8]) -> io::Result<()> {
unsafe fn kern_load(io: &Io, session: &mut Session, library: &[u8]) -> io::Result<(), ::std::io::Error> {
if session.running() {
unexpected!("attempted to load a new kernel while a kernel was running")
}
@ -200,8 +200,8 @@ unsafe fn kern_load(io: &Io, session: &mut Session, library: &[u8]) -> io::Resul
}
&kern::LoadReply(Err(ref error)) => {
kernel::stop();
Err(io::Error::new(io::ErrorKind::Other,
format!("cannot load kernel: {}", error)))
Err(io::Error::Other(::std::io::Error::new(::std::io::ErrorKind::Other,
format!("cannot load kernel: {}", error))))
}
other =>
unexpected!("unexpected reply from kernel CPU: {:?}", other)
@ -209,7 +209,7 @@ unsafe fn kern_load(io: &Io, session: &mut Session, library: &[u8]) -> io::Resul
})
}
fn kern_run(session: &mut Session) -> io::Result<()> {
fn kern_run(session: &mut Session) -> io::Result<(), ::std::io::Error> {
if session.kernel_state != KernelState::Loaded {
unexpected!("attempted to run a kernel while not in Loaded state")
}
@ -221,7 +221,7 @@ fn kern_run(session: &mut Session) -> io::Result<()> {
fn process_host_message(io: &Io,
stream: &mut TcpStream,
session: &mut Session) -> io::Result<()> {
session: &mut Session) -> io::Result<(), ::std::io::Error> {
match host_read(stream)? {
host::Request::SystemInfo => {
host_write(stream, host::Reply::SystemInfo {
@ -359,7 +359,7 @@ fn process_host_message(io: &Io,
}
fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>,
session: &mut Session) -> io::Result<bool> {
session: &mut Session) -> io::Result<bool, ::std::io::Error> {
kern_recv_notrace(io, |request| {
match (request, session.kernel_state) {
(&kern::LoadReply(_), KernelState::Loaded) |
@ -516,7 +516,7 @@ fn process_kern_message(io: &Io, mut stream: Option<&mut TcpStream>,
}
fn process_kern_queued_rpc(stream: &mut TcpStream,
_session: &mut Session) -> io::Result<()> {
_session: &mut Session) -> io::Result<(), ::std::io::Error> {
rpc_queue::dequeue(|slice| {
debug!("comm<-kern (async RPC)");
let length = NetworkEndian::read_u32(slice) as usize;
@ -529,7 +529,7 @@ fn process_kern_queued_rpc(stream: &mut TcpStream,
fn host_kernel_worker(io: &Io,
stream: &mut TcpStream,
congress: &mut Congress) -> io::Result<()> {
congress: &mut Congress) -> io::Result<(), ::std::io::Error> {
let mut session = Session::new(congress);
loop {
@ -568,7 +568,7 @@ fn host_kernel_worker(io: &Io,
fn flash_kernel_worker(io: &Io,
congress: &mut Congress,
config_key: &str) -> io::Result<()> {
config_key: &str) -> io::Result<(), ::std::io::Error> {
let mut session = Session::new(congress);
config::read(config_key, |result| {
@ -578,7 +578,8 @@ fn flash_kernel_worker(io: &Io,
// so make a copy.
kern_load(io, &mut session, Vec::from(kernel).as_ref())
},
_ => Err(io::Error::new(io::ErrorKind::NotFound, "kernel not found")),
_ => Err(io::Error::Other(::std::io::Error::new(::std::io::ErrorKind::NotFound,
"kernel not found"))),
}
})?;
kern_run(&mut session)?;
@ -639,13 +640,12 @@ pub fn thread(io: Io) {
info!("running startup kernel");
match flash_kernel_worker(&io, &mut congress, "startup_kernel") {
Ok(()) => info!("startup kernel finished"),
Err(io::Error::Other(ref err)) if err.kind() == ::std::io::ErrorKind::NotFound => {
info!("no startup kernel found")
}
Err(err) => {
if err.kind() == io::ErrorKind::NotFound {
info!("no startup kernel found")
} else {
congress.finished_cleanly.set(false);
error!("startup kernel aborted: {}", err);
}
congress.finished_cleanly.set(false);
error!("startup kernel aborted: {}", err);
}
}
})
@ -674,15 +674,16 @@ pub fn thread(io: Io) {
let mut stream = TcpStream::from_handle(&io, stream);
match host_kernel_worker(&io, &mut stream, &mut *congress) {
Ok(()) => (),
Err(io::Error::UnexpectedEof) => {
info!("connection closed");
}
Err(io::Error::Other(ref err))
if err.kind() == ::std::io::ErrorKind::Interrupted => {
info!("kernel interrupted");
}
Err(err) => {
if err.kind() == io::ErrorKind::UnexpectedEof {
info!("connection closed");
} else if err.kind() == io::ErrorKind::Interrupted {
info!("kernel interrupted");
} else {
congress.finished_cleanly.set(false);
error!("session aborted: {}", err);
}
congress.finished_cleanly.set(false);
error!("session aborted: {}", err);
}
}
});
@ -697,15 +698,17 @@ pub fn thread(io: Io) {
match flash_kernel_worker(&io, &mut *congress, "idle_kernel") {
Ok(()) =>
info!("idle kernel finished, standing by"),
Err(io::Error::Other(ref err))
if err.kind() == ::std::io::ErrorKind::Interrupted => {
info!("idle kernel interrupted");
}
Err(io::Error::Other(ref err))
if err.kind() == ::std::io::ErrorKind::NotFound => {
info!("no idle kernel found");
while io.relinquish().is_ok() {}
}
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 io.relinquish().is_ok() {}
} else {
error!("idle kernel aborted: {}", err);
}
error!("idle kernel aborted: {}", err);
}
}
})