mirror of https://github.com/m-labs/artiq.git
Rust: add support for artiq_corelog.
This commit is contained in:
parent
b14c19a886
commit
fdcb27ccff
|
@ -4,6 +4,8 @@ version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fringe 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fringe 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log_buffer 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lwip 0.0.0",
|
"lwip 0.0.0",
|
||||||
"std_artiq 0.0.0",
|
"std_artiq 0.0.0",
|
||||||
]
|
]
|
||||||
|
@ -30,6 +32,16 @@ name = "libc"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log_buffer"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lwip"
|
name = "lwip"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
@ -53,3 +65,5 @@ dependencies = [
|
||||||
"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
|
"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
|
||||||
"checksum fringe 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "987689dcfad85eee8d76b477865641ec483e63fb86d52966bfc350c4a647d78a"
|
"checksum fringe 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "987689dcfad85eee8d76b477865641ec483e63fb86d52966bfc350c4a647d78a"
|
||||||
"checksum libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "23e3757828fa702a20072c37ff47938e9dd331b92fac6e223d26d4b7a55f7ee2"
|
"checksum libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "23e3757828fa702a20072c37ff47938e9dd331b92fac6e223d26d4b7a55f7ee2"
|
||||||
|
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
|
||||||
|
"checksum log_buffer 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8beb5ba24eca52f9958874445c4de5e086a7e82a1ec6b7ab81e5fcfb134f25a"
|
||||||
|
|
|
@ -12,6 +12,8 @@ path = "src/lib.rs"
|
||||||
std_artiq = { path = "libstd_artiq" }
|
std_artiq = { path = "libstd_artiq" }
|
||||||
lwip = { path = "liblwip" }
|
lwip = { path = "liblwip" }
|
||||||
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 }
|
||||||
|
log_buffer = { version = "1.0" }
|
||||||
byteorder = { version = "0.5", default-features = false }
|
byteorder = { version = "0.5", default-features = false }
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
use core::mem;
|
||||||
|
use core::cell::RefCell;
|
||||||
|
use log::{self, Log, LogMetadata, LogRecord, LogLevelFilter};
|
||||||
|
use log_buffer::LogBuffer;
|
||||||
|
|
||||||
|
pub struct BufferLogger {
|
||||||
|
buffer: RefCell<LogBuffer<&'static mut [u8]>>
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can never preempt from within the logger, so there can be no data races.
|
||||||
|
unsafe impl Sync for BufferLogger {}
|
||||||
|
|
||||||
|
impl BufferLogger {
|
||||||
|
pub fn new(buffer: &'static mut [u8]) -> BufferLogger {
|
||||||
|
BufferLogger {
|
||||||
|
buffer: RefCell::new(LogBuffer::new(buffer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register<F: FnOnce(&BufferLogger)>(&self, f: F) {
|
||||||
|
// log::set_logger_raw captures a pointer to ourselves, so we must prevent
|
||||||
|
// ourselves from being moved or dropped after that function is called (and
|
||||||
|
// before log::shutdown_logger_raw is called).
|
||||||
|
unsafe {
|
||||||
|
log::set_logger_raw(|max_log_level| {
|
||||||
|
max_log_level.set(LogLevelFilter::Trace);
|
||||||
|
self as *const Log
|
||||||
|
}).expect("global logger can only be initialized once");
|
||||||
|
}
|
||||||
|
f(self);
|
||||||
|
log::shutdown_logger_raw().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.buffer.borrow_mut().clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract<R, F: FnOnce(&str) -> R>(&self, f: F) -> R {
|
||||||
|
f(self.buffer.borrow_mut().extract())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Log for BufferLogger {
|
||||||
|
fn enabled(&self, _metadata: &log::LogMetadata) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn log(&self, record: &LogRecord) {
|
||||||
|
if self.enabled(record.metadata()) {
|
||||||
|
use core::fmt::Write;
|
||||||
|
writeln!(self.buffer.borrow_mut(), "{}({}): {}",
|
||||||
|
record.level(), record.location().module_path(), record.args()).unwrap();
|
||||||
|
println!("{}({}): {}",
|
||||||
|
record.level(), record.location().module_path(), record.args());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,7 +39,7 @@ impl Scheduler {
|
||||||
Scheduler { threads: Vec::new(), index: 0 }
|
Scheduler { threads: Vec::new(), index: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn spawn<F: FnOnce(Waiter) + Send + 'static>(&mut self, stack_size: usize, f: F) {
|
pub unsafe fn spawn<F: FnOnce(Waiter) + Send>(&mut self, stack_size: usize, f: F) {
|
||||||
let stack = OwnedStack::new(stack_size);
|
let stack = OwnedStack::new(stack_size);
|
||||||
let thread = Thread {
|
let thread = Thread {
|
||||||
generator: Generator::unsafe_new(stack, move |yielder, _| {
|
generator: Generator::unsafe_new(stack, move |yielder, _| {
|
||||||
|
@ -286,8 +286,12 @@ impl<'a> Read for TcpStream<'a> {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||||
if self.buffer.is_none() {
|
if self.buffer.is_none() {
|
||||||
try!(self.waiter.tcp_readable(&self.lower));
|
try!(self.waiter.tcp_readable(&self.lower));
|
||||||
let pbuf = try!(self.lower.try_read()).unwrap();
|
match self.lower.try_read() {
|
||||||
self.buffer = Some((pbuf, 0))
|
Ok(Some(pbuf)) => self.buffer = Some((pbuf, 0)),
|
||||||
|
Ok(None) => unreachable!(),
|
||||||
|
Err(lwip::Error::ConnectionClosed) => return Ok(0),
|
||||||
|
Err(err) => return Err(Error::from(err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (pbuf, pos) = self.buffer.take().unwrap();
|
let (pbuf, pos) = self.buffer.take().unwrap();
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
#![feature(const_fn)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate std_artiq as std;
|
extern crate std_artiq as std;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
extern crate log_buffer;
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
|
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
|
use buffer_logger::BufferLogger;
|
||||||
|
|
||||||
pub mod io;
|
pub mod io;
|
||||||
|
pub mod buffer_logger;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
|
@ -16,13 +22,19 @@ extern {
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern fn rust_main() {
|
pub unsafe extern fn rust_main() {
|
||||||
println!("Accepting network sessions in Rust.");
|
static mut log_buffer: [u8; 4096] = [0; 4096];
|
||||||
|
BufferLogger::new(&mut log_buffer[..])
|
||||||
|
.register(move |logger| {
|
||||||
|
info!("Accepting network sessions in Rust.");
|
||||||
network_init();
|
network_init();
|
||||||
|
|
||||||
let mut scheduler = io::Scheduler::new();
|
let mut scheduler = io::Scheduler::new();
|
||||||
scheduler.spawn(4096, session::handler);
|
scheduler.spawn(4096, move |waiter| {
|
||||||
|
session::handler(waiter, logger)
|
||||||
|
});
|
||||||
loop {
|
loop {
|
||||||
lwip_service();
|
lwip_service();
|
||||||
scheduler.run()
|
scheduler.run()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::io::{self, Read};
|
use std::str;
|
||||||
|
use std::io::{self, Read, ErrorKind};
|
||||||
use self::protocol::*;
|
use self::protocol::*;
|
||||||
|
|
||||||
mod protocol;
|
mod protocol;
|
||||||
|
@ -52,15 +53,16 @@ fn check_magic(stream: &mut ::io::TcpStream) -> io::Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_request(stream: &mut ::io::TcpStream) -> io::Result<()> {
|
fn handle_request(stream: &mut ::io::TcpStream,
|
||||||
|
logger: &::buffer_logger::BufferLogger) -> io::Result<()> {
|
||||||
fn read_request(stream: &mut ::io::TcpStream) -> io::Result<Request> {
|
fn read_request(stream: &mut ::io::TcpStream) -> io::Result<Request> {
|
||||||
let request = try!(Request::read_from(stream));
|
let request = try!(Request::read_from(stream));
|
||||||
println!("comm<-host {:?}", request);
|
trace!("comm<-host {:?}", request);
|
||||||
Ok(request)
|
Ok(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_reply(stream: &mut ::io::TcpStream, reply: Reply) -> io::Result<()> {
|
fn write_reply(stream: &mut ::io::TcpStream, reply: Reply) -> io::Result<()> {
|
||||||
println!("comm->host {:?}", reply);
|
trace!("comm->host {:?}", reply);
|
||||||
reply.write_to(stream)
|
reply.write_to(stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,28 +77,50 @@ fn handle_request(stream: &mut ::io::TcpStream) -> io::Result<()> {
|
||||||
&ident[..ident.iter().position(|&c| c == 0).unwrap()]
|
&ident[..ident.iter().position(|&c| c == 0).unwrap()]
|
||||||
};
|
};
|
||||||
|
|
||||||
write_reply(stream, Reply::Ident(ident))
|
write_reply(stream, Reply::Ident(str::from_utf8(ident).unwrap()))
|
||||||
},
|
}
|
||||||
|
|
||||||
|
Request::Log => {
|
||||||
|
// Logging the packet with the log is inadvisable
|
||||||
|
trace!("comm->host Log(...)");
|
||||||
|
logger.extract(move |log| {
|
||||||
|
Reply::Log(log).write_to(stream)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Request::LogClear => {
|
||||||
|
logger.clear();
|
||||||
|
write_reply(stream, Reply::Log(""))
|
||||||
|
}
|
||||||
|
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_requests(stream: &mut ::io::TcpStream) -> io::Result<()> {
|
fn handle_requests(stream: &mut ::io::TcpStream,
|
||||||
|
logger: &::buffer_logger::BufferLogger) -> io::Result<()> {
|
||||||
try!(check_magic(stream));
|
try!(check_magic(stream));
|
||||||
loop {
|
loop {
|
||||||
try!(handle_request(stream))
|
try!(handle_request(stream, logger))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handler(waiter: ::io::Waiter) {
|
pub fn handler(waiter: ::io::Waiter,
|
||||||
|
logger: &::buffer_logger::BufferLogger) {
|
||||||
let addr = ::io::SocketAddr::new(::io::IP_ANY, 1381);
|
let addr = ::io::SocketAddr::new(::io::IP_ANY, 1381);
|
||||||
let listener = ::io::TcpListener::bind(waiter, addr).unwrap();
|
let listener = ::io::TcpListener::bind(waiter, addr).unwrap();
|
||||||
loop {
|
loop {
|
||||||
let (mut stream, _addr) = listener.accept().unwrap();
|
let (mut stream, addr) = listener.accept().unwrap();
|
||||||
match handle_requests(&mut stream) {
|
info!("new connection from {:?}", addr);
|
||||||
|
|
||||||
|
match handle_requests(&mut stream, logger) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("cannot handle network request: {:?}", err);
|
if err.kind() == ErrorKind::UnexpectedEof {
|
||||||
|
info!("connection closed");
|
||||||
|
} else {
|
||||||
|
error!("cannot handle network request: {:?}", err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,7 @@ impl Request {
|
||||||
pub enum Reply<'a> {
|
pub enum Reply<'a> {
|
||||||
Log(&'a str),
|
Log(&'a str),
|
||||||
|
|
||||||
Ident(&'a [u8]),
|
Ident(&'a str),
|
||||||
ClockSwitchCompleted,
|
ClockSwitchCompleted,
|
||||||
ClockSwitchFailed,
|
ClockSwitchFailed,
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ impl<'a> Reply<'a> {
|
||||||
Reply::Ident(ident) => {
|
Reply::Ident(ident) => {
|
||||||
try!(write_u8(&mut buf, 2));
|
try!(write_u8(&mut buf, 2));
|
||||||
try!(buf.write(b"AROR"));
|
try!(buf.write(b"AROR"));
|
||||||
try!(buf.write(ident));
|
try!(buf.write(ident.as_bytes()));
|
||||||
},
|
},
|
||||||
Reply::ClockSwitchCompleted => {
|
Reply::ClockSwitchCompleted => {
|
||||||
try!(write_u8(&mut buf, 3));
|
try!(write_u8(&mut buf, 3));
|
||||||
|
|
Loading…
Reference in New Issue