runtime: dirty hacks to remove allocations in ksupport.

This commit is contained in:
whitequark 2016-11-01 08:55:49 +00:00
parent c1e6d4b67c
commit 2095d01b84
7 changed files with 62 additions and 8 deletions

View File

@ -13,7 +13,7 @@ crate-type = ["staticlib"]
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
std_artiq = { path = "libstd_artiq" } std_artiq = { path = "libstd_artiq", features = ["alloc"] }
lwip = { path = "liblwip", default-features = false } lwip = { path = "liblwip", default-features = false }
fringe = { version = "= 1.1.0", default-features = false, features = ["alloc"] } fringe = { version = "= 1.1.0", default-features = false, features = ["alloc"] }
log = { version = "0.3", default-features = false, features = [] } log = { version = "0.3", default-features = false, features = [] }

View File

@ -127,7 +127,7 @@ extern fn send_async_rpc(service: u32, tag: *const u8, data: *const *const ()) {
}; };
proto::write_u32(&mut slice, length as u32) proto::write_u32(&mut slice, length as u32)
}).unwrap_or_else(|err| { }).unwrap_or_else(|err| {
assert!(err.kind() == std::io::ErrorKind::UnexpectedEof); assert!(err.kind() == std::io::ErrorKind::WriteZero);
send(&RpcSend { send(&RpcSend {
async: true, async: true,

View File

@ -9,7 +9,7 @@ path = "lib.rs"
[dependencies] [dependencies]
lwip-sys = { path = "../liblwip-sys" } lwip-sys = { path = "../liblwip-sys" }
std_artiq = { path = "../libstd_artiq" } std_artiq = { path = "../libstd_artiq", features = ["alloc"] }
[features] [features]
default = ["preemption"] default = ["preemption"]

View File

@ -9,3 +9,6 @@ path = "lib.rs"
[dependencies] [dependencies]
alloc_artiq = { path = "../liballoc_artiq" } alloc_artiq = { path = "../liballoc_artiq" }
[features]
alloc = []

View File

@ -8,7 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use alloc::boxed::Box; #[cfg(feature="alloc")] use alloc::boxed::Box;
#[cfg(not(feature="alloc"))] use ::FakeBox as Box;
use core::convert::Into; use core::convert::Into;
use core::fmt; use core::fmt;
use core::marker::{Send, Sync}; use core::marker::{Send, Sync};
@ -62,13 +63,19 @@ pub struct Error {
enum Repr { enum Repr {
Os(i32), Os(i32),
#[cfg(feature="alloc")]
Custom(Box<Custom>), Custom(Box<Custom>),
#[cfg(not(feature="alloc"))]
Custom(Custom),
} }
#[derive(Debug)] #[derive(Debug)]
struct Custom { struct Custom {
kind: ErrorKind, kind: ErrorKind,
#[cfg(feature="alloc")]
error: Box<error::Error+Send+Sync>, error: Box<error::Error+Send+Sync>,
#[cfg(not(feature="alloc"))]
error: &'static str
} }
/// A list specifying general categories of I/O error. /// A list specifying general categories of I/O error.
@ -162,12 +169,21 @@ impl Error {
/// // errors can also be created from other errors /// // errors can also be created from other errors
/// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
/// ``` /// ```
#[cfg(feature="alloc")]
pub fn new<E>(kind: ErrorKind, error: E) -> Error pub fn new<E>(kind: ErrorKind, error: E) -> Error
where E: Into<Box<error::Error+Send+Sync>> where E: Into<Box<error::Error+Send+Sync>>
{ {
Self::_new(kind, error.into()) Self::_new(kind, error.into())
} }
#[cfg(not(feature="alloc"))]
pub fn new<E>(kind: ErrorKind, error: E) -> Error
where E: Into<&'static str>
{
Self::_new(kind, error.into())
}
#[cfg(feature="alloc")]
fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error { fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error {
Error { Error {
repr: Repr::Custom(Box::new(Custom { repr: Repr::Custom(Box::new(Custom {
@ -177,6 +193,16 @@ impl Error {
} }
} }
#[cfg(not(feature="alloc"))]
fn _new(kind: ErrorKind, error: &'static str) -> Error {
Error {
repr: Repr::Custom(Box::new(Custom {
kind: kind,
error: error,
}))
}
}
/// Creates a new instance of an `Error` from a particular OS error code. /// Creates a new instance of an `Error` from a particular OS error code.
pub fn from_raw_os_error(code: i32) -> Error { pub fn from_raw_os_error(code: i32) -> Error {
Error { repr: Repr::Os(code) } Error { repr: Repr::Os(code) }
@ -198,6 +224,7 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
#[cfg(feature="alloc")]
pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> { pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
@ -210,6 +237,7 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
#[cfg(feature="alloc")]
pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> { pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
@ -221,6 +249,7 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
#[cfg(feature="alloc")]
pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> { pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
@ -282,14 +311,24 @@ impl error::Error for Error {
ErrorKind::UnexpectedEof => "unexpected end of file", ErrorKind::UnexpectedEof => "unexpected end of file",
ErrorKind::__Nonexhaustive => unreachable!() ErrorKind::__Nonexhaustive => unreachable!()
}, },
Repr::Custom(ref c) => c.error.description(), Repr::Custom(ref c) => {
#[cfg(feature="alloc")]
{ c.error.description() }
#[cfg(not(feature="alloc"))]
{ c.error }
},
} }
} }
fn cause(&self) -> Option<&error::Error> { fn cause(&self) -> Option<&error::Error> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
Repr::Custom(ref c) => c.error.cause(), Repr::Custom(ref _c) => {
#[cfg(feature="alloc")]
{ _c.error.cause() }
#[cfg(not(feature="alloc"))]
{ None }
}
} }
} }
} }

View File

@ -1,6 +1,7 @@
#![feature(lang_items, asm, alloc, collections, libc, needs_panic_runtime, #![feature(lang_items, asm, alloc, collections, libc, needs_panic_runtime,
question_mark, unicode, reflect_marker, raw, int_error_internals, question_mark, unicode, reflect_marker, raw, int_error_internals,
try_from, try_borrow, macro_reexport, allow_internal_unstable)] try_from, try_borrow, macro_reexport, allow_internal_unstable,
stmt_expr_attributes)]
#![no_std] #![no_std]
#![needs_panic_runtime] #![needs_panic_runtime]
@ -31,3 +32,13 @@ pub mod prelude {
pub mod error; pub mod error;
pub mod io; pub mod io;
// Provide Box::new wrapper
#[cfg(not(feature="alloc"))]
struct FakeBox<T>(core::marker::PhantomData<T>);
#[cfg(not(feature="alloc"))]
impl<T> FakeBox<T> {
fn new(val: T) -> T {
val
}
}

View File

@ -67,7 +67,8 @@ pub fn write_bytes(writer: &mut Write, value: &[u8]) -> io::Result<()> {
pub fn read_string(reader: &mut Read) -> io::Result<String> { pub fn read_string(reader: &mut Read) -> io::Result<String> {
let bytes = try!(read_bytes(reader)); let bytes = try!(read_bytes(reader));
String::from_utf8(bytes).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) String::from_utf8(bytes)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "invalid UTF-8"))
} }
pub fn write_string(writer: &mut Write, value: &str) -> io::Result<()> { pub fn write_string(writer: &mut Write, value: &str) -> io::Result<()> {