From a820ae98cf6b37d3442fe318a0d265ab8bc4c7a2 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 21 Apr 2017 17:20:50 +0000 Subject: [PATCH] ksupport: avoid allocations on I/O error paths. Fixes #715. --- artiq/firmware/libstd_artiq/Cargo.toml | 1 + artiq/firmware/libstd_artiq/io/error.rs | 34 ++++++++++++------------- artiq/firmware/libstd_artiq/lib.rs | 4 +-- artiq/firmware/runtime/Cargo.toml | 2 +- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/artiq/firmware/libstd_artiq/Cargo.toml b/artiq/firmware/libstd_artiq/Cargo.toml index dde6f0560..bc7034f51 100644 --- a/artiq/firmware/libstd_artiq/Cargo.toml +++ b/artiq/firmware/libstd_artiq/Cargo.toml @@ -9,3 +9,4 @@ path = "lib.rs" [features] alloc = [] +io_error_alloc = [] diff --git a/artiq/firmware/libstd_artiq/io/error.rs b/artiq/firmware/libstd_artiq/io/error.rs index 37ecc4507..942e4187c 100644 --- a/artiq/firmware/libstd_artiq/io/error.rs +++ b/artiq/firmware/libstd_artiq/io/error.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[cfg(feature="alloc")] use alloc::boxed::Box; -#[cfg(not(feature="alloc"))] use ::FakeBox as Box; +#[cfg(feature="io_error_alloc")] use alloc::boxed::Box; +#[cfg(not(feature="io_error_alloc"))] use ::FakeBox as Box; use core::convert::Into; use core::fmt; use core::marker::{Send, Sync}; @@ -63,18 +63,18 @@ pub struct Error { enum Repr { Os(i32), - #[cfg(feature="alloc")] + #[cfg(feature="io_error_alloc")] Custom(Box), - #[cfg(not(feature="alloc"))] + #[cfg(not(feature="io_error_alloc"))] Custom(Custom), } #[derive(Debug)] struct Custom { kind: ErrorKind, - #[cfg(feature="alloc")] + #[cfg(feature="io_error_alloc")] error: Box, - #[cfg(not(feature="alloc"))] + #[cfg(not(feature="io_error_alloc"))] error: &'static str } @@ -169,21 +169,21 @@ impl Error { /// // errors can also be created from other errors /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); /// ``` - #[cfg(feature="alloc")] + #[cfg(feature="io_error_alloc")] pub fn new(kind: ErrorKind, error: E) -> Error where E: Into> { Self::_new(kind, error.into()) } - #[cfg(not(feature="alloc"))] + #[cfg(not(feature="io_error_alloc"))] pub fn new(kind: ErrorKind, error: E) -> Error where E: Into<&'static str> { Self::_new(kind, error.into()) } - #[cfg(feature="alloc")] + #[cfg(feature="io_error_alloc")] fn _new(kind: ErrorKind, error: Box) -> Error { Error { repr: Repr::Custom(Box::new(Custom { @@ -193,7 +193,7 @@ impl Error { } } - #[cfg(not(feature="alloc"))] + #[cfg(not(feature="io_error_alloc"))] fn _new(kind: ErrorKind, error: &'static str) -> Error { Error { repr: Repr::Custom(Box::new(Custom { @@ -224,7 +224,7 @@ impl Error { /// /// If this `Error` was constructed via `new` then this function will /// return `Some`, otherwise it will return `None`. - #[cfg(feature="alloc")] + #[cfg(feature="io_error_alloc")] pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> { match self.repr { Repr::Os(..) => None, @@ -237,7 +237,7 @@ impl Error { /// /// If this `Error` was constructed via `new` then this function will /// return `Some`, otherwise it will return `None`. - #[cfg(feature="alloc")] + #[cfg(feature="io_error_alloc")] pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> { match self.repr { Repr::Os(..) => None, @@ -249,7 +249,7 @@ impl Error { /// /// If this `Error` was constructed via `new` then this function will /// return `Some`, otherwise it will return `None`. - #[cfg(feature="alloc")] + #[cfg(feature="io_error_alloc")] pub fn into_inner(self) -> Option> { match self.repr { Repr::Os(..) => None, @@ -312,9 +312,9 @@ impl error::Error for Error { ErrorKind::__Nonexhaustive => unreachable!() }, Repr::Custom(ref c) => { - #[cfg(feature="alloc")] + #[cfg(feature="io_error_alloc")] { c.error.description() } - #[cfg(not(feature="alloc"))] + #[cfg(not(feature="io_error_alloc"))] { c.error } }, } @@ -324,9 +324,9 @@ impl error::Error for Error { match self.repr { Repr::Os(..) => None, Repr::Custom(ref _c) => { - #[cfg(feature="alloc")] + #[cfg(feature="io_error_alloc")] { _c.error.cause() } - #[cfg(not(feature="alloc"))] + #[cfg(not(feature="io_error_alloc"))] { None } } } diff --git a/artiq/firmware/libstd_artiq/lib.rs b/artiq/firmware/libstd_artiq/lib.rs index 8ab6ac86b..483926220 100644 --- a/artiq/firmware/libstd_artiq/lib.rs +++ b/artiq/firmware/libstd_artiq/lib.rs @@ -31,9 +31,9 @@ pub mod error; pub mod io; // Provide Box::new wrapper -#[cfg(not(feature="alloc"))] +#[cfg(any(not(feature="alloc"), not(feature="io_error_alloc")))] struct FakeBox(core::marker::PhantomData); -#[cfg(not(feature="alloc"))] +#[cfg(any(not(feature="alloc"), not(feature="io_error_alloc")))] impl FakeBox { fn new(val: T) -> T { val diff --git a/artiq/firmware/runtime/Cargo.toml b/artiq/firmware/runtime/Cargo.toml index 237d88a65..dc6c497ac 100644 --- a/artiq/firmware/runtime/Cargo.toml +++ b/artiq/firmware/runtime/Cargo.toml @@ -18,7 +18,7 @@ cslice = { version = "0.3" } log = { version = "0.3", default-features = false } fringe = { version = "= 1.1.0", default-features = false, features = ["alloc"] } alloc_artiq = { path = "../liballoc_artiq" } -std_artiq = { path = "../libstd_artiq", features = ["alloc"] } +std_artiq = { path = "../libstd_artiq", features = ["alloc", "io_error_alloc"] } logger_artiq = { path = "../liblogger_artiq" } board = { path = "../libboard", features = ["uart_console"] } proto = { path = "../libproto", features = ["log"] }