forked from M-Labs/artiq
runtime: remove unnecessary buffering.
This commit is contained in:
parent
edafb08b43
commit
557bc4bb56
@ -20,7 +20,7 @@ class _H2DMsgType(Enum):
|
||||
IDENT_REQUEST = 3
|
||||
SWITCH_CLOCK = 4
|
||||
|
||||
LOAD_LIBRARY = 5
|
||||
LOAD_KERNEL = 5
|
||||
RUN_KERNEL = 6
|
||||
|
||||
RPC_REPLY = 7
|
||||
@ -68,9 +68,7 @@ RPCKeyword = namedtuple('RPCKeyword', ['name', 'value'])
|
||||
|
||||
class CommGeneric:
|
||||
def __init__(self):
|
||||
self._read_type = self._write_type = None
|
||||
self._read_length = 0
|
||||
self._write_buffer = []
|
||||
self._read_type = None
|
||||
|
||||
def open(self):
|
||||
"""Opens the communication channel.
|
||||
@ -99,10 +97,6 @@ class CommGeneric:
|
||||
def _read_header(self):
|
||||
self.open()
|
||||
|
||||
if self._read_length > 0:
|
||||
raise IOError("Read underrun ({} bytes remaining)".
|
||||
format(self._read_length))
|
||||
|
||||
# Wait for a synchronization sequence, 5a 5a 5a 5a.
|
||||
sync_count = 0
|
||||
while sync_count < 4:
|
||||
@ -113,20 +107,11 @@ class CommGeneric:
|
||||
sync_count = 0
|
||||
|
||||
# Read message header.
|
||||
(self._read_length, ) = struct.unpack(">l", self.read(4))
|
||||
if not self._read_length: # inband connection close
|
||||
raise OSError("Connection closed")
|
||||
|
||||
(raw_type, ) = struct.unpack("B", self.read(1))
|
||||
self._read_type = _D2HMsgType(raw_type)
|
||||
|
||||
if self._read_length < 9:
|
||||
raise IOError("Read overrun in message header ({} remaining)".
|
||||
format(self._read_length))
|
||||
self._read_length -= 9
|
||||
|
||||
logger.debug("receiving message: type=%r length=%d",
|
||||
self._read_type, self._read_length)
|
||||
logger.debug("receiving message: type=%r",
|
||||
self._read_type)
|
||||
|
||||
def _read_expect(self, ty):
|
||||
if self._read_type != ty:
|
||||
@ -138,12 +123,6 @@ class CommGeneric:
|
||||
self._read_expect(ty)
|
||||
|
||||
def _read_chunk(self, length):
|
||||
if self._read_length < length:
|
||||
raise IOError("Read overrun while trying to read {} bytes ({} remaining)"
|
||||
" in packet {}".
|
||||
format(length, self._read_length, self._read_type))
|
||||
|
||||
self._read_length -= length
|
||||
return self.read(length)
|
||||
|
||||
def _read_int8(self):
|
||||
@ -175,43 +154,32 @@ class CommGeneric:
|
||||
def _write_header(self, ty):
|
||||
self.open()
|
||||
|
||||
logger.debug("preparing to send message: type=%r", ty)
|
||||
self._write_type = ty
|
||||
self._write_buffer = []
|
||||
logger.debug("sending message: type=%r", ty)
|
||||
|
||||
def _write_flush(self):
|
||||
# Calculate message size.
|
||||
length = sum([len(chunk) for chunk in self._write_buffer])
|
||||
logger.debug("sending message: type=%r length=%d", self._write_type, length)
|
||||
|
||||
# Write synchronization sequence, header and body.
|
||||
self.write(struct.pack(">llB", 0x5a5a5a5a,
|
||||
9 + length, self._write_type.value))
|
||||
for chunk in self._write_buffer:
|
||||
self.write(chunk)
|
||||
# Write synchronization sequence and header.
|
||||
self.write(struct.pack(">lB", 0x5a5a5a5a, ty.value))
|
||||
|
||||
def _write_empty(self, ty):
|
||||
self._write_header(ty)
|
||||
self._write_flush()
|
||||
|
||||
def _write_chunk(self, chunk):
|
||||
self._write_buffer.append(chunk)
|
||||
self.write(chunk)
|
||||
|
||||
def _write_int8(self, value):
|
||||
self._write_buffer.append(struct.pack("B", value))
|
||||
self.write(struct.pack("B", value))
|
||||
|
||||
def _write_int32(self, value):
|
||||
self._write_buffer.append(struct.pack(">l", value))
|
||||
self.write(struct.pack(">l", value))
|
||||
|
||||
def _write_int64(self, value):
|
||||
self._write_buffer.append(struct.pack(">q", value))
|
||||
self.write(struct.pack(">q", value))
|
||||
|
||||
def _write_float64(self, value):
|
||||
self._write_buffer.append(struct.pack(">d", value))
|
||||
self.write(struct.pack(">d", value))
|
||||
|
||||
def _write_bytes(self, value):
|
||||
self._write_int32(len(value))
|
||||
self._write_buffer.append(value)
|
||||
self.write(value)
|
||||
|
||||
def _write_string(self, value):
|
||||
self._write_bytes(value.encode("utf-8"))
|
||||
@ -232,7 +200,7 @@ class CommGeneric:
|
||||
if runtime_id != b"AROR":
|
||||
raise UnsupportedDevice("Unsupported runtime ID: {}"
|
||||
.format(runtime_id))
|
||||
gateware_version = self._read_chunk(self._read_length).decode("utf-8")
|
||||
gateware_version = self._read_string()
|
||||
if gateware_version != software_version and \
|
||||
gateware_version + ".dirty" != software_version:
|
||||
logger.warning("Mismatch between gateware (%s) "
|
||||
@ -242,7 +210,6 @@ class CommGeneric:
|
||||
def switch_clock(self, external):
|
||||
self._write_header(_H2DMsgType.SWITCH_CLOCK)
|
||||
self._write_int8(external)
|
||||
self._write_flush()
|
||||
|
||||
self._read_empty(_D2HMsgType.CLOCK_SWITCH_COMPLETED)
|
||||
|
||||
@ -251,7 +218,7 @@ class CommGeneric:
|
||||
|
||||
self._read_header()
|
||||
self._read_expect(_D2HMsgType.LOG_REPLY)
|
||||
return self._read_chunk(self._read_length).decode("utf-8", "replace")
|
||||
return self._read_string()
|
||||
|
||||
def clear_log(self):
|
||||
self._write_empty(_H2DMsgType.LOG_CLEAR)
|
||||
@ -261,17 +228,15 @@ class CommGeneric:
|
||||
def flash_storage_read(self, key):
|
||||
self._write_header(_H2DMsgType.FLASH_READ_REQUEST)
|
||||
self._write_string(key)
|
||||
self._write_flush()
|
||||
|
||||
self._read_header()
|
||||
self._read_expect(_D2HMsgType.FLASH_READ_REPLY)
|
||||
return self._read_chunk(self._read_length)
|
||||
return self._read_string()
|
||||
|
||||
def flash_storage_write(self, key, value):
|
||||
self._write_header(_H2DMsgType.FLASH_WRITE_REQUEST)
|
||||
self._write_string(key)
|
||||
self._write_bytes(value)
|
||||
self._write_flush()
|
||||
|
||||
self._read_header()
|
||||
if self._read_type == _D2HMsgType.FLASH_ERROR_REPLY:
|
||||
@ -287,14 +252,12 @@ class CommGeneric:
|
||||
def flash_storage_remove(self, key):
|
||||
self._write_header(_H2DMsgType.FLASH_REMOVE_REQUEST)
|
||||
self._write_string(key)
|
||||
self._write_flush()
|
||||
|
||||
self._read_empty(_D2HMsgType.FLASH_OK_REPLY)
|
||||
|
||||
def load(self, kernel_library):
|
||||
self._write_header(_H2DMsgType.LOAD_LIBRARY)
|
||||
self._write_chunk(kernel_library)
|
||||
self._write_flush()
|
||||
self._write_header(_H2DMsgType.LOAD_KERNEL)
|
||||
self._write_bytes(kernel_library)
|
||||
|
||||
self._read_empty(_D2HMsgType.LOAD_COMPLETED)
|
||||
|
||||
@ -460,7 +423,6 @@ class CommGeneric:
|
||||
self._write_header(_H2DMsgType.RPC_REPLY)
|
||||
self._write_bytes(return_tags)
|
||||
self._send_rpc_value(bytearray(return_tags), result, result, service)
|
||||
self._write_flush()
|
||||
except Exception as exn:
|
||||
logger.debug("rpc service: %d %r %r ! %r", service_id, args, kwargs, exn)
|
||||
|
||||
@ -503,8 +465,6 @@ class CommGeneric:
|
||||
self._write_int32(-1) # column not known
|
||||
self._write_string(function)
|
||||
|
||||
self._write_flush()
|
||||
|
||||
def _serve_exception(self, embedding_map, symbolizer, demangler):
|
||||
name = self._read_string()
|
||||
message = self._read_string()
|
||||
|
@ -233,31 +233,29 @@ fn process_host_message(waiter: Waiter,
|
||||
Err(_) => host_write(stream, host::Reply::KernelStartupFailed)
|
||||
},
|
||||
|
||||
host::Request::RpcReply { tag, data } => {
|
||||
host::Request::RpcReply { tag } => {
|
||||
if session.kernel_state != KernelState::RpcWait {
|
||||
unexpected!("unsolicited RPC reply")
|
||||
}
|
||||
|
||||
try!(kern_recv(waiter, |reply| {
|
||||
let slot = try!(kern_recv(waiter, |reply| {
|
||||
match reply {
|
||||
kern::RpcRecvRequest { slot } => {
|
||||
let mut data = io::Cursor::new(data);
|
||||
rpc::recv_return(&mut data, &tag, slot, &|size| {
|
||||
try!(kern_send(waiter, kern::RpcRecvReply {
|
||||
alloc_size: size, exception: None
|
||||
}));
|
||||
kern_recv(waiter, |reply| {
|
||||
match reply {
|
||||
kern::RpcRecvRequest { slot } => Ok(slot),
|
||||
_ => unreachable!()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
kern::RpcRecvRequest { slot } => Ok(slot),
|
||||
other =>
|
||||
unexpected!("unexpected reply from kernel CPU: {:?}", other)
|
||||
}
|
||||
}));
|
||||
try!(rpc::recv_return(stream, &tag, slot, &|size| {
|
||||
try!(kern_send(waiter, kern::RpcRecvReply {
|
||||
alloc_size: size, exception: None
|
||||
}));
|
||||
kern_recv(waiter, |reply| {
|
||||
match reply {
|
||||
kern::RpcRecvRequest { slot } => Ok(slot),
|
||||
_ => unreachable!()
|
||||
}
|
||||
})
|
||||
}));
|
||||
try!(kern_send(waiter, kern::RpcRecvReply { alloc_size: 0, exception: None }));
|
||||
|
||||
session.kernel_state = KernelState::Running;
|
||||
@ -352,12 +350,10 @@ fn process_kern_message(waiter: Waiter,
|
||||
match stream {
|
||||
None => unexpected!("unexpected RPC in flash kernel"),
|
||||
Some(ref mut stream) => {
|
||||
let mut buf = Vec::new();
|
||||
try!(rpc::send_args(&mut buf, tag, data));
|
||||
try!(host_write(stream, host::Reply::RpcRequest {
|
||||
service: service,
|
||||
data: &buf[..]
|
||||
service: service
|
||||
}));
|
||||
try!(rpc::send_args(stream, tag, data));
|
||||
if !batch {
|
||||
session.kernel_state = KernelState::RpcWait
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ pub enum Request {
|
||||
LoadKernel(Vec<u8>),
|
||||
RunKernel,
|
||||
|
||||
RpcReply { tag: Vec<u8>, data: Vec<u8> },
|
||||
RpcReply { tag: Vec<u8> },
|
||||
RpcException {
|
||||
name: String,
|
||||
message: String,
|
||||
@ -45,29 +45,17 @@ pub enum Request {
|
||||
|
||||
impl Request {
|
||||
pub fn read_from(reader: &mut Read) -> io::Result<Request> {
|
||||
const HEADER_SIZE: usize = 9;
|
||||
|
||||
try!(read_sync(reader));
|
||||
let length = try!(read_u32(reader)) as usize;
|
||||
let ty = try!(read_u8(reader));
|
||||
|
||||
Ok(match ty {
|
||||
Ok(match try!(read_u8(reader)) {
|
||||
1 => Request::Log,
|
||||
2 => Request::LogClear,
|
||||
3 => Request::Ident,
|
||||
4 => Request::SwitchClock(try!(read_u8(reader))),
|
||||
5 => {
|
||||
let mut code = vec![0; length - HEADER_SIZE];
|
||||
try!(reader.read_exact(&mut code));
|
||||
Request::LoadKernel(code)
|
||||
}
|
||||
5 => Request::LoadKernel(try!(read_bytes(reader))),
|
||||
6 => Request::RunKernel,
|
||||
7 => {
|
||||
let tag = try!(read_bytes(reader));
|
||||
let mut data = vec![0; length - HEADER_SIZE - 4 - tag.len()];
|
||||
try!(reader.read_exact(&mut data));
|
||||
Request::RpcReply { tag: tag, data: data }
|
||||
}
|
||||
7 => Request::RpcReply {
|
||||
tag: try!(read_bytes(reader))
|
||||
},
|
||||
8 => Request::RpcException {
|
||||
name: try!(read_string(reader)),
|
||||
message: try!(read_string(reader)),
|
||||
@ -119,7 +107,7 @@ pub enum Reply<'a> {
|
||||
backtrace: &'a [usize]
|
||||
},
|
||||
|
||||
RpcRequest { service: u32, data: &'a [u8] },
|
||||
RpcRequest { service: u32 },
|
||||
|
||||
FlashRead(&'a [u8]),
|
||||
FlashOk,
|
||||
@ -131,88 +119,80 @@ pub enum Reply<'a> {
|
||||
|
||||
impl<'a> Reply<'a> {
|
||||
pub fn write_to(&self, writer: &mut Write) -> io::Result<()> {
|
||||
let mut buf = Vec::new();
|
||||
try!(write_sync(&mut buf));
|
||||
try!(write_u32(&mut buf, 0)); // length placeholder
|
||||
|
||||
try!(write_sync(writer));
|
||||
match *self {
|
||||
Reply::Log(ref log) => {
|
||||
try!(write_u8(&mut buf, 1));
|
||||
try!(buf.write(log.as_bytes()));
|
||||
try!(write_u8(writer, 1));
|
||||
try!(write_string(writer, log));
|
||||
},
|
||||
|
||||
Reply::Ident(ident) => {
|
||||
try!(write_u8(&mut buf, 2));
|
||||
try!(buf.write(b"AROR"));
|
||||
try!(buf.write(ident.as_bytes()));
|
||||
try!(write_u8(writer, 2));
|
||||
try!(writer.write(b"AROR"));
|
||||
try!(write_string(writer, ident));
|
||||
},
|
||||
Reply::ClockSwitchCompleted => {
|
||||
try!(write_u8(&mut buf, 3));
|
||||
try!(write_u8(writer, 3));
|
||||
},
|
||||
Reply::ClockSwitchFailed => {
|
||||
try!(write_u8(&mut buf, 4));
|
||||
try!(write_u8(writer, 4));
|
||||
},
|
||||
|
||||
Reply::LoadCompleted => {
|
||||
try!(write_u8(&mut buf, 5));
|
||||
try!(write_u8(writer, 5));
|
||||
},
|
||||
Reply::LoadFailed => {
|
||||
try!(write_u8(&mut buf, 6));
|
||||
try!(write_u8(writer, 6));
|
||||
},
|
||||
|
||||
Reply::KernelFinished => {
|
||||
try!(write_u8(&mut buf, 7));
|
||||
try!(write_u8(writer, 7));
|
||||
},
|
||||
Reply::KernelStartupFailed => {
|
||||
try!(write_u8(&mut buf, 8));
|
||||
try!(write_u8(writer, 8));
|
||||
},
|
||||
Reply::KernelException {
|
||||
name, message, param, file, line, column, function, backtrace
|
||||
} => {
|
||||
try!(write_u8(&mut buf, 9));
|
||||
try!(write_string(&mut buf, name));
|
||||
try!(write_string(&mut buf, message));
|
||||
try!(write_u64(&mut buf, param[0]));
|
||||
try!(write_u64(&mut buf, param[1]));
|
||||
try!(write_u64(&mut buf, param[2]));
|
||||
try!(write_string(&mut buf, file));
|
||||
try!(write_u32(&mut buf, line));
|
||||
try!(write_u32(&mut buf, column));
|
||||
try!(write_string(&mut buf, function));
|
||||
try!(write_u32(&mut buf, backtrace.len() as u32));
|
||||
try!(write_u8(writer, 9));
|
||||
try!(write_string(writer, name));
|
||||
try!(write_string(writer, message));
|
||||
try!(write_u64(writer, param[0]));
|
||||
try!(write_u64(writer, param[1]));
|
||||
try!(write_u64(writer, param[2]));
|
||||
try!(write_string(writer, file));
|
||||
try!(write_u32(writer, line));
|
||||
try!(write_u32(writer, column));
|
||||
try!(write_string(writer, function));
|
||||
try!(write_u32(writer, backtrace.len() as u32));
|
||||
for &addr in backtrace {
|
||||
try!(write_u32(&mut buf, addr as u32))
|
||||
try!(write_u32(writer, addr as u32))
|
||||
}
|
||||
},
|
||||
|
||||
Reply::RpcRequest { service, data } => {
|
||||
try!(write_u8(&mut buf, 10));
|
||||
try!(write_u32(&mut buf, service));
|
||||
try!(buf.write(data));
|
||||
Reply::RpcRequest { service } => {
|
||||
try!(write_u8(writer, 10));
|
||||
try!(write_u32(writer, service));
|
||||
},
|
||||
|
||||
Reply::FlashRead(ref bytes) => {
|
||||
try!(write_u8(&mut buf, 11));
|
||||
try!(buf.write(bytes));
|
||||
try!(write_u8(writer, 11));
|
||||
try!(write_bytes(writer, bytes));
|
||||
},
|
||||
Reply::FlashOk => {
|
||||
try!(write_u8(&mut buf, 12));
|
||||
try!(write_u8(writer, 12));
|
||||
},
|
||||
Reply::FlashError => {
|
||||
try!(write_u8(&mut buf, 13));
|
||||
try!(write_u8(writer, 13));
|
||||
},
|
||||
|
||||
Reply::WatchdogExpired => {
|
||||
try!(write_u8(&mut buf, 14));
|
||||
try!(write_u8(writer, 14));
|
||||
},
|
||||
Reply::ClockFailure => {
|
||||
try!(write_u8(&mut buf, 15));
|
||||
try!(write_u8(writer, 15));
|
||||
},
|
||||
}
|
||||
|
||||
let len = buf.len();
|
||||
try!(write_u32(&mut &mut buf[4..8], len as u32));
|
||||
|
||||
writer.write_all(&buf)
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user