forked from M-Labs/artiq
firmware: use &CSlice for lists
This commit is contained in:
parent
eb6817c8f1
commit
ebfeb1869f
|
@ -15,7 +15,7 @@ extern crate proto_artiq;
|
||||||
extern crate riscv;
|
extern crate riscv;
|
||||||
|
|
||||||
use core::{mem, ptr, slice, str, convert::TryFrom};
|
use core::{mem, ptr, slice, str, convert::TryFrom};
|
||||||
use cslice::{CSlice, AsCSlice};
|
use cslice::CSlice;
|
||||||
use io::Cursor;
|
use io::Cursor;
|
||||||
use dyld::Library;
|
use dyld::Library;
|
||||||
use board_artiq::{mailbox, rpc_queue};
|
use board_artiq::{mailbox, rpc_queue};
|
||||||
|
@ -190,13 +190,12 @@ fn terminate(exceptions: &'static [Option<eh_artiq::Exception<'static>>],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unwind(aborts)]
|
#[unwind(aborts)]
|
||||||
extern fn cache_get<'a>(ret: &'a mut CSlice<i32>, key: &CSlice<u8>) -> &'a CSlice<'a, i32> {
|
extern fn cache_get<'a>(key: &CSlice<u8>) -> *const CSlice<'a, i32> {
|
||||||
send(&CacheGetRequest {
|
send(&CacheGetRequest {
|
||||||
key: str::from_utf8(key.as_ref()).unwrap()
|
key: str::from_utf8(key.as_ref()).unwrap()
|
||||||
});
|
});
|
||||||
recv!(&CacheGetReply { value } => {
|
recv!(&CacheGetReply { value } => {
|
||||||
*ret = value.as_c_slice();
|
value
|
||||||
ret
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
use cslice::CSlice;
|
||||||
use dyld;
|
use dyld;
|
||||||
|
|
||||||
pub const KERNELCPU_EXEC_ADDRESS: usize = 0x45000000;
|
pub const KERNELCPU_EXEC_ADDRESS: usize = 0x45000000;
|
||||||
|
@ -53,7 +54,7 @@ pub enum Message<'a> {
|
||||||
RpcFlush,
|
RpcFlush,
|
||||||
|
|
||||||
CacheGetRequest { key: &'a str },
|
CacheGetRequest { key: &'a str },
|
||||||
CacheGetReply { value: &'static [i32] },
|
CacheGetReply { value: *const CSlice<'static, i32> },
|
||||||
CachePutRequest { key: &'a str, value: &'a [i32] },
|
CachePutRequest { key: &'a str, value: &'a [i32] },
|
||||||
CachePutReply { succeeded: bool },
|
CachePutReply { succeeded: bool },
|
||||||
|
|
||||||
|
|
|
@ -70,16 +70,17 @@ unsafe fn recv_value<R, E>(reader: &mut R, tag: Tag, data: &mut *mut (),
|
||||||
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| {
|
||||||
(*ptr).length = reader.read_u32()?;
|
|
||||||
let length = (*ptr).length as usize;
|
|
||||||
|
|
||||||
let tag = it.clone().next().expect("truncated tag");
|
let tag = it.clone().next().expect("truncated tag");
|
||||||
let padding = if let Tag::Int64 | Tag::Float64 = tag { 4 } else { 0 };
|
let padding = if let Tag::Int64 | Tag::Float64 = tag { 4 } else { 0 };
|
||||||
let mut data = alloc(tag.size() * length + padding)?;
|
|
||||||
|
|
||||||
data = data.offset(alignment_offset(tag.alignment() as isize, data as isize));
|
let length = reader.read_u32()? as usize;
|
||||||
|
let data = alloc(tag.size() * length + padding + 8)? as *mut u8;
|
||||||
|
*ptr = data as *mut List;
|
||||||
|
let ptr = data as *mut List;
|
||||||
|
let mut data = data.offset(8 + alignment_offset(tag.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 => {
|
||||||
|
@ -221,11 +222,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 usize;
|
let length = (**ptr).length as usize;
|
||||||
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 {
|
||||||
// we cannot use NativeEndian::from_slice_i32 as the data is not mutable,
|
// we cannot use NativeEndian::from_slice_i32 as the data is not mutable,
|
||||||
|
|
|
@ -1,27 +1,50 @@
|
||||||
use alloc::{vec::Vec, string::String, collections::btree_map::BTreeMap};
|
use alloc::{vec::Vec, string::String, collections::btree_map::BTreeMap};
|
||||||
|
use cslice::{CSlice, AsCSlice};
|
||||||
|
use core::mem::transmute;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
data: Vec<i32>,
|
data: Vec<i32>,
|
||||||
|
slice: CSlice<'static, i32>,
|
||||||
borrowed: bool
|
borrowed: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
impl core::fmt::Debug for Entry {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
f.debug_struct("Entry")
|
||||||
|
.field("data", &self.data)
|
||||||
|
.field("borrowed", &self.borrowed)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Cache {
|
pub struct Cache {
|
||||||
entries: BTreeMap<String, Entry>
|
entries: BTreeMap<String, Entry>,
|
||||||
|
empty: CSlice<'static, i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Debug for Cache {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
f.debug_struct("Cache")
|
||||||
|
.field("entries", &self.entries)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cache {
|
impl Cache {
|
||||||
pub fn new() -> Cache {
|
pub fn new() -> Cache {
|
||||||
Cache { entries: BTreeMap::new() }
|
let empty_vec = vec![];
|
||||||
|
let empty = unsafe {
|
||||||
|
transmute::<CSlice<'_, i32>, CSlice<'static, i32>>(empty_vec.as_c_slice())
|
||||||
|
};
|
||||||
|
Cache { entries: BTreeMap::new(), empty }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&mut self, key: &str) -> *const [i32] {
|
pub fn get(&mut self, key: &str) -> *const CSlice<'static, i32> {
|
||||||
match self.entries.get_mut(key) {
|
match self.entries.get_mut(key) {
|
||||||
None => &[],
|
None => &self.empty,
|
||||||
Some(ref mut entry) => {
|
Some(ref mut entry) => {
|
||||||
entry.borrowed = true;
|
entry.borrowed = true;
|
||||||
&entry.data[..]
|
&entry.slice
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,12 +55,21 @@ impl Cache {
|
||||||
Some(ref mut entry) => {
|
Some(ref mut entry) => {
|
||||||
if entry.borrowed { return Err(()) }
|
if entry.borrowed { return Err(()) }
|
||||||
entry.data = Vec::from(data);
|
entry.data = Vec::from(data);
|
||||||
|
unsafe {
|
||||||
|
entry.slice = transmute::<CSlice<'_, i32>, CSlice<'static, i32>>(
|
||||||
|
entry.data.as_c_slice());
|
||||||
|
}
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let data = Vec::from(data);
|
||||||
|
let slice = unsafe {
|
||||||
|
transmute::<CSlice<'_, i32>, CSlice<'static, i32>>(data.as_c_slice())
|
||||||
|
};
|
||||||
self.entries.insert(String::from(key), Entry {
|
self.entries.insert(String::from(key), Entry {
|
||||||
data: Vec::from(data),
|
data,
|
||||||
|
slice,
|
||||||
borrowed: false
|
borrowed: false
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -418,7 +418,7 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
|
||||||
kern_send(io, &kern::CacheGetReply {
|
kern_send(io, &kern::CacheGetReply {
|
||||||
// Zing! This transmute is only safe because we dynamically track
|
// Zing! This transmute is only safe because we dynamically track
|
||||||
// whether the kernel has borrowed any values from the cache.
|
// whether the kernel has borrowed any values from the cache.
|
||||||
value: unsafe { mem::transmute::<*const [i32], &'static [i32]>(value) }
|
value: unsafe { mem::transmute(value) }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue