Compare commits

...

1 Commits

Author SHA1 Message Date
85ea6f0b32 runtime: use &CSlice for lists 2022-03-10 16:09:19 +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 cslice::{CSlice, AsCSlice};
use core::mem::{transmute, forget}; use core::mem::{transmute, forget};
use super::{KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0, Message}; 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(); let key = String::from_utf8(key.as_ref().to_vec()).unwrap();
unsafe { unsafe {
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::CacheGetRequest(key)); KERNEL_CHANNEL_1TO0.as_mut().unwrap().send(Message::CacheGetRequest(key));
let msg = KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv(); let msg = KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv();
if let Message::CacheGetReply(v) = msg { if let Message::CacheGetReply(v) = msg {
let slice = transmute(v.as_c_slice()); let leaked = Box::new(v.as_c_slice());
// we intentionally leak the memory here, let reference = transmute(leaked.as_ref());
// which does not matter as core1 would restart forget(leaked);
forget(v); forget(v);
slice reference
} else { } else {
panic!("Expected CacheGetReply for CacheGetRequest"); 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 key = String::from_utf8(key.as_ref().to_vec()).unwrap();
let value = list.as_ref().to_vec(); let value = list.as_ref().to_vec();
unsafe { unsafe {

View File

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