forked from M-Labs/artiq
firmware: migrate rpc_proto to new libio.
This closes an old and horrible issue in that some code in ksupport may implicitly try to allocate and we'll never know until it crashes at runtime inside liballoc_stub. This also removes liballoc_stub. This also removes ReadExt and WriteExt from libproto. Hooray!
This commit is contained in:
parent
9a1bd66d2c
commit
6a10d54432
9
artiq/firmware/Cargo.lock
generated
9
artiq/firmware/Cargo.lock
generated
@ -2,10 +2,6 @@
|
||||
name = "alloc_list"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "alloc_stub"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "amp"
|
||||
version = "0.0.0"
|
||||
@ -146,15 +142,13 @@ dependencies = [
|
||||
name = "ksupport"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc_stub 0.0.0",
|
||||
"amp 0.0.0",
|
||||
"board 0.0.0",
|
||||
"build_misoc 0.0.0",
|
||||
"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)",
|
||||
"dyld 0.0.0",
|
||||
"io 0.0.0",
|
||||
"proto 0.0.0",
|
||||
"std_artiq 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -211,7 +205,6 @@ dependencies = [
|
||||
"dyld 0.0.0",
|
||||
"io 0.0.0",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"std_artiq 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -13,10 +13,8 @@ crate-type = ["staticlib"]
|
||||
build_misoc = { path = "../libbuild_misoc" }
|
||||
|
||||
[dependencies]
|
||||
byteorder = { version = "1.0", default-features = false }
|
||||
cslice = { version = "0.3" }
|
||||
alloc_stub = { path = "../liballoc_stub" }
|
||||
std_artiq = { path = "../libstd_artiq" }
|
||||
io = { path = "../libio", features = ["byteorder"] }
|
||||
dyld = { path = "../libdyld" }
|
||||
board = { path = "../libboard" }
|
||||
proto = { path = "../libproto" }
|
||||
|
@ -1,31 +1,27 @@
|
||||
#![feature(lang_items, asm, libc, panic_unwind, unwind_attributes, global_allocator)]
|
||||
#![feature(lang_items, asm, libc, panic_unwind, unwind_attributes, global_allocator,
|
||||
needs_panic_runtime)]
|
||||
#![no_std]
|
||||
#![needs_panic_runtime]
|
||||
|
||||
extern crate byteorder;
|
||||
extern crate cslice;
|
||||
extern crate unwind;
|
||||
extern crate libc;
|
||||
|
||||
extern crate alloc_stub;
|
||||
extern crate std_artiq as std;
|
||||
extern crate io;
|
||||
extern crate board;
|
||||
extern crate dyld;
|
||||
extern crate proto;
|
||||
extern crate amp;
|
||||
|
||||
use core::{mem, ptr, slice, str};
|
||||
use std::io::Cursor;
|
||||
use cslice::{CSlice, AsCSlice};
|
||||
use alloc_stub::StubAlloc;
|
||||
use io::Cursor;
|
||||
use board::csr;
|
||||
use dyld::Library;
|
||||
use proto::{kernel_proto, rpc_proto};
|
||||
use proto::kernel_proto::*;
|
||||
use amp::{mailbox, rpc_queue};
|
||||
|
||||
#[global_allocator]
|
||||
static mut ALLOC: StubAlloc = StubAlloc;
|
||||
|
||||
fn send(request: &Message) {
|
||||
unsafe { mailbox::send(request as *const _ as usize) }
|
||||
while !mailbox::acknowledged() {}
|
||||
@ -131,9 +127,9 @@ extern fn rpc_send_async(service: u32, tag: CSlice<u8>, data: *const *const ())
|
||||
rpc_proto::send_args(&mut writer, service, tag.as_ref(), data)?;
|
||||
writer.position()
|
||||
};
|
||||
proto::WriteExt::write_u32(&mut slice, length as u32)
|
||||
io::proto::ProtoWrite::write_u32(&mut slice, length as u32)
|
||||
}).unwrap_or_else(|err| {
|
||||
assert!(err.kind() == std::io::ErrorKind::WriteZero);
|
||||
assert!(err == io::Error::UnexpectedEof);
|
||||
|
||||
while !rpc_queue::empty() {}
|
||||
send(&RpcSend {
|
||||
|
@ -1,8 +0,0 @@
|
||||
[package]
|
||||
authors = ["M-Labs"]
|
||||
name = "alloc_stub"
|
||||
version = "0.0.0"
|
||||
|
||||
[lib]
|
||||
name = "alloc_stub"
|
||||
path = "lib.rs"
|
@ -1,18 +0,0 @@
|
||||
#![feature(alloc, allocator_api)]
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::allocator::{Layout, AllocErr, Alloc};
|
||||
|
||||
pub struct StubAlloc;
|
||||
|
||||
unsafe impl<'a> Alloc for &'a StubAlloc {
|
||||
unsafe fn alloc(&mut self, _layout: Layout) -> Result<*mut u8, AllocErr> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&mut self, _ptr: *mut u8, _layout: Layout) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
@ -99,6 +99,23 @@ pub trait Write {
|
||||
fn size_hint(&mut self, _min: usize, _max: Option<usize>) {}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std_artiq"))]
|
||||
impl<'a> Write for &'a mut [u8] {
|
||||
type WriteError = !;
|
||||
type FlushError = !;
|
||||
|
||||
fn write(&mut self, buf: &[u8]) -> result::Result<usize, Self::WriteError> {
|
||||
let len = buf.len().min(self.len());
|
||||
self[..len].copy_from_slice(&buf[..len]);
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> result::Result<(), Self::FlushError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CursorError {
|
||||
EndOfBuffer
|
||||
|
@ -1,15 +1,19 @@
|
||||
#[cfg(feature = "alloc")]
|
||||
use core::fmt;
|
||||
#[cfg(feature = "alloc")]
|
||||
use alloc::string;
|
||||
use byteorder::{ByteOrder, NetworkEndian};
|
||||
|
||||
use ::{Read, Write, Error as IoError};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[derive(Debug)]
|
||||
pub enum ReadStringError<T> {
|
||||
Utf8Error(string::FromUtf8Error),
|
||||
Other(T)
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<T: fmt::Display> fmt::Display for ReadStringError<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
@ -21,6 +25,7 @@ impl<T: fmt::Display> fmt::Display for ReadStringError<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<T> From<ReadStringError<IoError<T>>> for IoError<T>
|
||||
{
|
||||
fn from(value: ReadStringError<IoError<T>>) -> IoError<T> {
|
||||
@ -31,6 +36,7 @@ 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>
|
||||
|
@ -11,6 +11,8 @@ path = "lib.rs"
|
||||
byteorder = { version = "1.0", default-features = false }
|
||||
cslice = { version = "0.3" }
|
||||
log = { version = "0.4", default-features = false, optional = true }
|
||||
io = { path = "../libio", features = ["byteorder", "alloc"] }
|
||||
std_artiq = { path = "../libstd_artiq", features = ["alloc"] }
|
||||
io = { path = "../libio", features = ["byteorder"] }
|
||||
dyld = { path = "../libdyld" }
|
||||
|
||||
[features]
|
||||
alloc = ["io/alloc"]
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![no_std]
|
||||
#![feature(alloc)]
|
||||
#![cfg_attr(feature = "alloc", feature(alloc))]
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
extern crate byteorder;
|
||||
extern crate cslice;
|
||||
#[cfg(feature = "log")]
|
||||
#[macro_use]
|
||||
@ -10,97 +10,17 @@ extern crate log;
|
||||
|
||||
extern crate io;
|
||||
extern crate dyld;
|
||||
extern crate std_artiq as std;
|
||||
|
||||
// Internal protocols.
|
||||
pub mod kernel_proto;
|
||||
|
||||
// External protocols.
|
||||
#[cfg(feature = "alloc")]
|
||||
pub mod mgmt_proto;
|
||||
#[cfg(feature = "alloc")]
|
||||
pub mod analyzer_proto;
|
||||
#[cfg(feature = "alloc")]
|
||||
pub mod moninj_proto;
|
||||
#[cfg(feature = "alloc")]
|
||||
pub mod session_proto;
|
||||
pub mod rpc_proto;
|
||||
|
||||
use std::io::{Read, Write, Result, Error, ErrorKind};
|
||||
use std::vec::Vec;
|
||||
use std::string::String;
|
||||
use byteorder::{ByteOrder, NetworkEndian};
|
||||
|
||||
pub trait ReadExt: Read {
|
||||
fn read_u8(&mut self) -> Result<u8> {
|
||||
let mut bytes = [0; 1];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(bytes[0])
|
||||
}
|
||||
|
||||
fn read_u16(&mut self) -> Result<u16> {
|
||||
let mut bytes = [0; 2];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(NetworkEndian::read_u16(&bytes))
|
||||
}
|
||||
|
||||
fn read_u32(&mut self) -> Result<u32> {
|
||||
let mut bytes = [0; 4];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(NetworkEndian::read_u32(&bytes))
|
||||
}
|
||||
|
||||
fn read_u64(&mut self) -> Result<u64> {
|
||||
let mut bytes = [0; 8];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(NetworkEndian::read_u64(&bytes))
|
||||
}
|
||||
|
||||
fn read_bytes(&mut self) -> Result<Vec<u8>> {
|
||||
let length = self.read_u32()?;
|
||||
let mut value = Vec::new();
|
||||
value.resize(length as usize, 0);
|
||||
self.read_exact(&mut value)?;
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn read_string(&mut self) -> Result<String> {
|
||||
let bytes = self.read_bytes()?;
|
||||
String::from_utf8(bytes)
|
||||
.map_err(|_| Error::new(ErrorKind::InvalidData, "invalid UTF-8"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + ?Sized> ReadExt for R {}
|
||||
|
||||
pub trait WriteExt: Write {
|
||||
fn write_u8(&mut self, value: u8) -> Result<()> {
|
||||
let bytes = [value; 1];
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
fn write_u16(&mut self, value: u16) -> Result<()> {
|
||||
let mut bytes = [0; 2];
|
||||
NetworkEndian::write_u16(&mut bytes, value);
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
fn write_u32(&mut self, value: u32) -> Result<()> {
|
||||
let mut bytes = [0; 4];
|
||||
NetworkEndian::write_u32(&mut bytes, value);
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
fn write_u64(&mut self, value: u64) -> Result<()> {
|
||||
let mut bytes = [0; 8];
|
||||
NetworkEndian::write_u64(&mut bytes, value);
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
fn write_bytes(&mut self, value: &[u8]) -> Result<()> {
|
||||
self.write_u32(value.len() as u32)?;
|
||||
self.write_all(value)
|
||||
}
|
||||
|
||||
fn write_string(&mut self, value: &str) -> Result<()> {
|
||||
self.write_bytes(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write + ?Sized> WriteExt for W {}
|
||||
|
@ -1,11 +1,16 @@
|
||||
use std::io::{self, Read, Write};
|
||||
use std::str;
|
||||
use core::str;
|
||||
use cslice::{CSlice, CMutSlice};
|
||||
use {ReadExt, WriteExt};
|
||||
|
||||
use io::{Read, Write, Result};
|
||||
use io::proto::{ProtoRead, ProtoWrite};
|
||||
|
||||
use self::tag::{Tag, TagIterator, split_tag};
|
||||
|
||||
unsafe fn recv_value(reader: &mut Read, tag: Tag, data: &mut *mut (),
|
||||
alloc: &Fn(usize) -> io::Result<*mut ()>) -> io::Result<()> {
|
||||
unsafe fn recv_value<T>(reader: &mut T, tag: Tag, data: &mut *mut (),
|
||||
alloc: &Fn(usize) -> Result<*mut (), T::ReadError>)
|
||||
-> Result<(), T::ReadError>
|
||||
where T: Read + ?Sized
|
||||
{
|
||||
macro_rules! consume_value {
|
||||
($ty:ty, |$ptr:ident| $map:expr) => ({
|
||||
let $ptr = (*data) as *mut $ty;
|
||||
@ -71,8 +76,11 @@ unsafe fn recv_value(reader: &mut Read, tag: Tag, data: &mut *mut (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recv_return(reader: &mut Read, tag_bytes: &[u8], data: *mut (),
|
||||
alloc: &Fn(usize) -> io::Result<*mut ()>) -> io::Result<()> {
|
||||
pub fn recv_return<T>(reader: &mut T, tag_bytes: &[u8], data: *mut (),
|
||||
alloc: &Fn(usize) -> Result<*mut (), T::ReadError>)
|
||||
-> Result<(), T::ReadError>
|
||||
where T: Read + ?Sized
|
||||
{
|
||||
let mut it = TagIterator::new(tag_bytes);
|
||||
#[cfg(feature = "log")]
|
||||
debug!("recv ...->{}", it);
|
||||
@ -84,7 +92,10 @@ pub fn recv_return(reader: &mut Read, tag_bytes: &[u8], data: *mut (),
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn send_value(writer: &mut Write, tag: Tag, data: &mut *const ()) -> io::Result<()> {
|
||||
unsafe fn send_value<T>(writer: &mut T, tag: Tag, data: &mut *const ())
|
||||
-> Result<(), T::WriteError>
|
||||
where T: Write + ?Sized
|
||||
{
|
||||
macro_rules! consume_value {
|
||||
($ty:ty, |$ptr:ident| $map:expr) => ({
|
||||
let $ptr = (*data) as *const $ty;
|
||||
@ -158,8 +169,10 @@ unsafe fn send_value(writer: &mut Write, tag: Tag, data: &mut *const ()) -> io::
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_args(writer: &mut Write, service: u32, tag_bytes: &[u8],
|
||||
data: *const *const ()) -> io::Result<()> {
|
||||
pub fn send_args<T>(writer: &mut T, service: u32, tag_bytes: &[u8], data: *const *const ())
|
||||
-> Result<(), T::WriteError>
|
||||
where T: Write + ?Sized
|
||||
{
|
||||
let (arg_tags_bytes, return_tag_bytes) = split_tag(tag_bytes);
|
||||
|
||||
let mut args_it = TagIterator::new(arg_tags_bytes);
|
||||
|
@ -19,13 +19,13 @@ 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 = ["std_artiq"] }
|
||||
io = { path = "../libio", features = ["byteorder", "std_artiq"] }
|
||||
board = { path = "../libboard", features = ["uart_console", "smoltcp"] }
|
||||
alloc_list = { path = "../liballoc_list" }
|
||||
std_artiq = { path = "../libstd_artiq", features = ["alloc", "io_error_alloc"] }
|
||||
logger_artiq = { path = "../liblogger_artiq" }
|
||||
board_artiq = { path = "../libboard_artiq" }
|
||||
proto = { path = "../libproto", features = ["log"] }
|
||||
proto = { path = "../libproto", features = ["log", "alloc"] }
|
||||
amp = { path = "../libamp" }
|
||||
drtioaux = { path = "../libdrtioaux" }
|
||||
|
||||
|
@ -12,6 +12,7 @@ extern crate smoltcp;
|
||||
|
||||
extern crate alloc_list;
|
||||
extern crate unwind_backtrace;
|
||||
extern crate io;
|
||||
#[macro_use]
|
||||
extern crate std_artiq as std;
|
||||
extern crate logger_artiq;
|
||||
|
@ -1,10 +1,11 @@
|
||||
use board::boot;
|
||||
use std::io::{self, Read, Write};
|
||||
use log::{self, LevelFilter};
|
||||
|
||||
use io::proto::ProtoWrite;
|
||||
use board::boot;
|
||||
use logger_artiq::BufferLogger;
|
||||
use sched::Io;
|
||||
use sched::{TcpListener, TcpStream};
|
||||
use proto::WriteExt;
|
||||
use mgmt_proto::*;
|
||||
use profiler;
|
||||
|
||||
|
@ -313,12 +313,12 @@ fn process_host_message(io: &Io,
|
||||
})?;
|
||||
rpc::recv_return(stream, &tag, slot, &|size| {
|
||||
kern_send(io, &kern::RpcRecvReply(Ok(size)))?;
|
||||
kern_recv(io, |reply| {
|
||||
Ok(kern_recv(io, |reply| {
|
||||
match reply {
|
||||
&kern::RpcRecvRequest(slot) => Ok(slot),
|
||||
other => unexpected!("unexpected reply from kernel CPU: {:?}", other)
|
||||
}
|
||||
})
|
||||
})?)
|
||||
})?;
|
||||
kern_send(io, &kern::RpcRecvReply(Ok(0)))?;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user