runtime: use &CSlice for lists #175

Merged
sb10q merged 1 commits from pca006132/artiq-zynq:list-repr into master 2022-03-10 16:30:34 +08:00
2 changed files with 20 additions and 17 deletions

View File

@ -1,26 +1,26 @@
use alloc::string::String;
use alloc::{string::String, boxed::Box};
use cslice::{CSlice, AsCSlice};
use core::mem::{transmute, forget};
use super::{KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, Message};
pub extern fn get(key: CSlice<u8>) -> CSlice<'static, i32> {
pub extern fn get(key: CSlice<u8>) -> &CSlice<'static, i32> {
let key = String::from_utf8(key.as_ref().to_vec()).unwrap();
unsafe {
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::CacheGetRequest(key));
let msg = KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv();
if let Message::CacheGetReply(v) = msg {
let slice = transmute(v.as_c_slice());
// we intentionally leak the memory here,
// which does not matter as core1 would restart
let leaked = Box::new(v.as_c_slice());
let reference = transmute(leaked.as_ref());
forget(leaked);
forget(v);
slice
reference
} else {
panic!("Expected CacheGetReply for CacheGetRequest");
}
}
}
pub extern fn put(key: CSlice<u8>, list: CSlice<i32>) {
pub extern fn put(key: CSlice<u8>, list: &CSlice<i32>) {
let key = String::from_utf8(key.as_ref().to_vec()).unwrap();
let value = list.as_ref().to_vec();
unsafe {

View File

@ -82,19 +82,22 @@ async unsafe fn recv_value<F>(stream: &TcpStream, tag: Tag<'async_recursion>, da
Tag::List(it) => {
#[repr(C)]
struct List { elements: *mut (), length: u32 }
consume_value!(List, |ptr| {
consume_value!(*mut List, |ptr| {
let length = proto_async::read_i32(stream).await? as usize;
(*ptr).length = length as u32;
let tag = it.clone().next().expect("truncated tag");
let data_size = tag.size() * length as usize +
match tag {
Tag::Int64 | Tag::Float64 => 4,
_ => 0
};
let mut data = alloc(data_size).await;
let data = alloc(data_size + 8).await as *mut u8;
*ptr = data as *mut List;
let ptr = data as *mut List;
let data = data.offset(8);
let alignment = tag.alignment();
data = data.offset(alignment_offset(alignment as isize, data as isize));
let mut data = data.offset(alignment_offset(alignment as isize, data as isize)) as *mut ();
(*ptr).length = length as u32;
(*ptr).elements = data;
match tag {
Tag::Bool => {
@ -250,11 +253,11 @@ unsafe fn send_value<W>(writer: &mut W, tag: Tag, data: &mut *const ())
Tag::List(it) => {
#[repr(C)]
struct List { elements: *const (), length: u32 }
consume_value!(List, |ptr| {
let length = (*ptr).length as isize;
consume_value!(&List, |ptr| {
let length = (**ptr).length as isize;
writer.write_u32((*ptr).length)?;
let tag = it.clone().next().expect("truncated tag");
let mut data = (*ptr).elements;
let mut data = (**ptr).elements;
writer.write_u8(tag.as_u8())?;
match tag {
Tag::Bool => {
@ -446,10 +449,10 @@ mod tag {
it.take(3).map(|t| t.alignment()).max().unwrap()
}
// CSlice basically
Tag::Bytes | Tag::String | Tag::ByteArray | Tag::List(_) =>
Tag::Bytes | Tag::String | Tag::ByteArray =>
core::mem::align_of::<CSlice<()>>(),
// array buffer is allocated, so no need for alignment first
Tag::Array(_, _) => 1,
Tag::List(_) | Tag::Array(_, _) => 1,
// will not be sent from the host
_ => unreachable!("unexpected tag from host")
}
@ -477,7 +480,7 @@ mod tag {
}
size
}
Tag::List(_) => 8,
Tag::List(_) => 4,
Tag::Array(_, num_dims) => 4 * (1 + num_dims as usize),
Tag::Range(it) => {
let tag = it.clone().next().expect("truncated tag");