diff --git a/async-usercalls/src/alloc/allocator.rs b/async-usercalls/src/alloc/allocator.rs deleted file mode 100644 index 7c6cef9f..00000000 --- a/async-usercalls/src/alloc/allocator.rs +++ /dev/null @@ -1,145 +0,0 @@ -use super::slab::{BufSlab, Slab, SlabAllocator, User, MAX_COUNT}; -use std::cmp; -use std::os::fortanix_sgx::usercalls::raw::ByteBuffer; - -pub const MIN_BUF_SIZE: usize = 1 << 5; // 32 bytes -pub const MAX_BUF_SIZE: usize = 1 << 16; // 64 KB -pub const NUM_SIZES: usize = 1 + (MAX_BUF_SIZE / MIN_BUF_SIZE).trailing_zeros() as usize; - -pub struct SharedAllocator { - by_size: Vec>, - byte_buffers: Vec>, -} - -unsafe impl Send for SharedAllocator {} -unsafe impl Sync for SharedAllocator {} - -impl SharedAllocator { - pub fn new(buf_counts: [usize; NUM_SIZES], byte_buffer_count: usize) -> Self { - let mut by_size = Vec::with_capacity(NUM_SIZES); - for i in 0..NUM_SIZES { - by_size.push(make_buf_slabs(buf_counts[i], MIN_BUF_SIZE << i)); - } - let byte_buffers = make_byte_buffers(byte_buffer_count); - Self { by_size, byte_buffers } - } - - pub fn alloc_buf(&self, size: usize) -> Option> { - assert!(size > 0); - if size > MAX_BUF_SIZE { - return None; - } - let (_, index) = size_index(size); - self.by_size[index].alloc() - } - - pub fn alloc_byte_buffer(&self) -> Option> { - self.byte_buffers.alloc() - } -} - -pub struct LocalAllocator { - initial_buf_counts: [usize; NUM_SIZES], - initial_byte_buffer_count: usize, - inner: SharedAllocator, -} - -impl LocalAllocator { - pub fn new(initial_buf_counts: [usize; NUM_SIZES], initial_byte_buffer_count: usize) -> Self { - let mut by_size = Vec::with_capacity(NUM_SIZES); - by_size.resize_with(NUM_SIZES, Default::default); - let byte_buffers = Vec::new(); - Self { - initial_buf_counts, - initial_byte_buffer_count, - inner: SharedAllocator { by_size, byte_buffers }, - } - } - - pub fn alloc_buf(&mut self, request_size: usize) -> User<[u8]> { - assert!(request_size > 0); - if request_size > MAX_BUF_SIZE { - // Always allocate very large buffers directly - return User::<[u8]>::uninitialized(request_size); - } - let (size, index) = size_index(request_size); - if let Some(buf) = self.inner.by_size[index].alloc() { - return buf; - } - let slabs = &mut self.inner.by_size[index]; - if slabs.len() >= 8 { - // Keep the number of slabs for each size small. - return User::<[u8]>::uninitialized(request_size); - } - let count = slabs.last().map_or(self.initial_buf_counts[index], |s| s.count() * 2); - // Limit each slab's count for better worst-case performance. - let count = cmp::min(count, MAX_COUNT / 8); - slabs.push(BufSlab::new(count, size)); - slabs.last().unwrap().alloc().expect("fresh slab failed to allocate") - } - - pub fn alloc_byte_buffer(&mut self) -> User { - let bbs = &mut self.inner.byte_buffers; - if let Some(byte_buffer) = bbs.alloc() { - return byte_buffer; - } - if bbs.len() >= 8 { - // Keep the number of slabs small. - return User::::uninitialized(); - } - let count = bbs.last().map_or(self.initial_byte_buffer_count, |s| s.count() * 2); - // Limit each slab's count for better worst-case performance. - let count = cmp::min(count, MAX_COUNT / 8); - bbs.push(Slab::new(count)); - bbs.last().unwrap().alloc().expect("fresh slab failed to allocate") - } -} - -fn make_buf_slabs(count: usize, size: usize) -> Vec { - match count { - 0 => Vec::new(), - n if n < 1024 => vec![BufSlab::new(n, size)], - n if n < 4 * 1024 => vec![BufSlab::new(n / 2, size), BufSlab::new(n / 2, size)], - n if n < 32 * 1024 => vec![ - BufSlab::new(n / 4, size), - BufSlab::new(n / 4, size), - BufSlab::new(n / 4, size), - BufSlab::new(n / 4, size), - ], - n => vec![ - BufSlab::new(n / 8, size), - BufSlab::new(n / 8, size), - BufSlab::new(n / 8, size), - BufSlab::new(n / 8, size), - BufSlab::new(n / 8, size), - BufSlab::new(n / 8, size), - BufSlab::new(n / 8, size), - BufSlab::new(n / 8, size), - ], - } -} - -fn make_byte_buffers(count: usize) -> Vec> { - match count { - 0 => Vec::new(), - n if n < 1024 => vec![Slab::new(n)], - n if n < 4 * 1024 => vec![Slab::new(n / 2), Slab::new(n / 2)], - n if n < 32 * 1024 => vec![Slab::new(n / 4), Slab::new(n / 4), Slab::new(n / 4), Slab::new(n / 4)], - n => vec![ - Slab::new(n / 8), - Slab::new(n / 8), - Slab::new(n / 8), - Slab::new(n / 8), - Slab::new(n / 8), - Slab::new(n / 8), - Slab::new(n / 8), - Slab::new(n / 8), - ], - } -} - -fn size_index(request_size: usize) -> (usize, usize) { - let size = cmp::max(MIN_BUF_SIZE, request_size.next_power_of_two()); - let index = (size / MIN_BUF_SIZE).trailing_zeros() as usize; - (size, index) -} diff --git a/async-usercalls/src/alloc/bitmap.rs b/async-usercalls/src/alloc/bitmap.rs deleted file mode 100644 index 80da1cca..00000000 --- a/async-usercalls/src/alloc/bitmap.rs +++ /dev/null @@ -1,156 +0,0 @@ -use spin::Mutex; -use std::sync::atomic::*; - -pub struct OptionalBitmap(BitmapKind); - -struct LargeBitmap(Mutex); - -struct LargeBitmapInner { - bits: Box<[u64]>, - unset_count: usize, // optimization -} - -enum BitmapKind { - None, - V1(AtomicU8), - V2(AtomicU16), - V3(AtomicU32), - V4(AtomicU64), - V5(LargeBitmap), -} - -impl OptionalBitmap { - pub fn none() -> Self { - Self(BitmapKind::None) - } - - /// `bit_count` must be >= 8 and a power of two - pub fn new(bit_count: usize) -> Self { - Self(match bit_count { - 8 => BitmapKind::V1(AtomicU8::new(0)), - 16 => BitmapKind::V2(AtomicU16::new(0)), - 32 => BitmapKind::V3(AtomicU32::new(0)), - 64 => BitmapKind::V4(AtomicU64::new(0)), - n if n > 0 && n % 64 == 0 => { - let bits = vec![0u64; n / 64].into_boxed_slice(); - BitmapKind::V5(LargeBitmap(Mutex::new(LargeBitmapInner { - bits, - unset_count: bit_count, - }))) - } - _ => panic!("bit_count must be >= 8 and a power of two"), - }) - } - - /// set the bit at given index to 0 and panic if the old value was not 1. - pub fn unset(&self, index: usize) { - match self.0 { - BitmapKind::None => {} - BitmapKind::V1(ref a) => a.unset(index), - BitmapKind::V2(ref b) => b.unset(index), - BitmapKind::V3(ref c) => c.unset(index), - BitmapKind::V4(ref d) => d.unset(index), - BitmapKind::V5(ref e) => e.unset(index), - } - } - - /// return the index of a previously unset bit and set that bit to 1. - pub fn reserve(&self) -> Option { - match self.0 { - BitmapKind::None => None, - BitmapKind::V1(ref a) => a.reserve(), - BitmapKind::V2(ref b) => b.reserve(), - BitmapKind::V3(ref c) => c.reserve(), - BitmapKind::V4(ref d) => d.reserve(), - BitmapKind::V5(ref e) => e.reserve(), - } - } -} - -trait BitmapOps { - fn unset(&self, index: usize); - fn reserve(&self) -> Option; -} - -macro_rules! impl_bitmap_ops { - ( $( $t:ty ),* $(,)? ) => {$( - impl BitmapOps for $t { - fn unset(&self, index: usize) { - let bit = 1 << index; - let old = self.fetch_and(!bit, Ordering::Release) & bit; - assert!(old != 0); - } - - fn reserve(&self) -> Option { - let initial = self.load(Ordering::Relaxed); - let unset_count = initial.count_zeros(); - let (mut index, mut bit) = match unset_count { - 0 => return None, - _ => (0, 1), - }; - for _ in 0..unset_count { - // find the next unset bit - while bit & initial != 0 { - index += 1; - bit = bit << 1; - } - let old = self.fetch_or(bit, Ordering::Acquire) & bit; - if old == 0 { - return Some(index); - } - index += 1; - bit = bit << 1; - } - None - } - } - )*}; -} - -impl_bitmap_ops!(AtomicU8, AtomicU16, AtomicU32, AtomicU64); - -impl BitmapOps for LargeBitmap { - fn unset(&self, index: usize) { - let mut inner = self.0.lock(); - let array = &mut inner.bits; - assert!(index < array.len() * 64); - let slot = index / 64; - let offset = index % 64; - let element = &mut array[slot]; - - let bit = 1 << offset; - let old = *element & bit; - *element = *element & !bit; - inner.unset_count += 1; - assert!(old != 0); - } - - fn reserve(&self) -> Option { - let mut inner = self.0.lock(); - if inner.unset_count == 0 { - return None; - } - let array = &mut inner.bits; - for slot in 0..array.len() { - if let (Some(offset), val) = reserve_u64(array[slot]) { - array[slot] = val; - inner.unset_count -= 1; - return Some(slot * 64 + offset); - } - } - unreachable!() - } -} - -fn reserve_u64(element: u64) -> (Option, u64) { - let (mut index, mut bit) = match element.count_zeros() { - 0 => return (None, element), - _ => (0, 1), - }; - // find the first unset bit - while bit & element != 0 { - index += 1; - bit = bit << 1; - } - (Some(index), element | bit) -} diff --git a/async-usercalls/src/alloc/mod.rs b/async-usercalls/src/alloc/mod.rs deleted file mode 100644 index d1a1abff..00000000 --- a/async-usercalls/src/alloc/mod.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::cell::RefCell; -use std::os::fortanix_sgx::usercalls::raw::ByteBuffer; - -mod allocator; -mod bitmap; -mod slab; -#[cfg(test)] -mod tests; - -use self::allocator::{LocalAllocator, SharedAllocator}; -pub use self::slab::{User, UserSafeExt}; - -/// Allocates a slice of bytes in userspace that is at least as large as `size`. -pub fn alloc_buf(size: usize) -> User<[u8]> { - if let Some(buf) = SHARED.alloc_buf(size) { - return buf; - } - LOCAL.with(|local| local.borrow_mut().alloc_buf(size)) -} - -/// Allocates a `ByteBuffer` in userspace. -pub fn alloc_byte_buffer() -> User { - if let Some(bb) = SHARED.alloc_byte_buffer() { - return bb; - } - LOCAL.with(|local| local.borrow_mut().alloc_byte_buffer()) -} - -lazy_static::lazy_static! { - static ref SHARED: SharedAllocator = SharedAllocator::new( - [ - 8192, // x 32 bytes - 4096, // x 64 bytes - 2048, // x 128 bytes - 1024, // x 256 bytes - 512, // x 512 bytes - 256, // x 1 KB - 64, // x 2 KB - 32, // x 4 KB - 16, // x 8 KB - 1024, // x 16 KB - 32, // x 32 KB - 16, // x 64 KB - ], - 8192, // x ByteBuffer(s) - ); -} - -std::thread_local! { - static LOCAL: RefCell = RefCell::new(LocalAllocator::new( - [ - 128, // x 32 bytes - 64, // x 64 bytes - 32, // x 128 bytes - 16, // x 256 bytes - 8, // x 512 bytes - 8, // x 1 KB - 8, // x 2 KB - 8, // x 4 KB - 8, // x 8 KB - 8, // x 16 KB - 8, // x 32 KB - 8, // x 64 KB - ], - 64, // x ByteBuffer(s) - )); -} diff --git a/async-usercalls/src/alloc/slab.rs b/async-usercalls/src/alloc/slab.rs deleted file mode 100644 index a9e0a0c4..00000000 --- a/async-usercalls/src/alloc/slab.rs +++ /dev/null @@ -1,198 +0,0 @@ -use super::bitmap::OptionalBitmap; -use std::cell::UnsafeCell; -use std::mem; -use std::ops::{Deref, DerefMut}; -use std::os::fortanix_sgx::usercalls::alloc::{User as StdUser, UserRef, UserSafe, UserSafeSized}; -use std::sync::Arc; - -pub const MIN_COUNT: usize = 8; -pub const MAX_COUNT: usize = 64 * 1024; -pub const MIN_UNIT_LEN: usize = 32; - -pub trait SlabAllocator { - type Output; - - fn alloc(&self) -> Option; - fn count(&self) -> usize; - fn total_size(&self) -> usize; -} - -impl SlabAllocator for Vec { - type Output = A::Output; - - fn alloc(&self) -> Option { - for a in self.iter() { - if let Some(buf) = a.alloc() { - return Some(buf); - } - } - None - } - - fn count(&self) -> usize { - self.iter().map(|a| a.count()).sum() - } - - fn total_size(&self) -> usize { - self.iter().map(|a| a.total_size()).sum() - } -} - -struct Storage { - user: UnsafeCell>, - bitmap: OptionalBitmap, -} - -pub struct BufSlab { - storage: Arc>, - unit_len: usize, -} - -impl BufSlab { - pub fn new(count: usize, unit_len: usize) -> Self { - assert!(count.is_power_of_two() && count >= MIN_COUNT && count <= MAX_COUNT); - assert!(unit_len.is_power_of_two() && unit_len >= MIN_UNIT_LEN); - BufSlab { - storage: Arc::new(Storage { - user: UnsafeCell::new(StdUser::<[u8]>::uninitialized(count * unit_len)), - bitmap: OptionalBitmap::new(count), - }), - unit_len, - } - } -} - -impl SlabAllocator for BufSlab { - type Output = User<[u8]>; - - fn alloc(&self) -> Option { - let index = self.storage.bitmap.reserve()?; - let start = index * self.unit_len; - let end = start + self.unit_len; - let user = unsafe { &mut *self.storage.user.get() }; - let user_ref = &mut user[start..end]; - Some(User { - user_ref, - storage: self.storage.clone(), - index, - }) - } - - fn count(&self) -> usize { - self.total_size() / self.unit_len - } - - fn total_size(&self) -> usize { - let user = unsafe { &*self.storage.user.get() }; - user.len() - } -} - -pub trait UserSafeExt: UserSafe { - type Element: UserSafeSized; -} - -impl UserSafeExt for [T] { - type Element = T; -} - -impl UserSafeExt for T { - type Element = T; -} - -pub struct User { - user_ref: &'static mut UserRef, - storage: Arc>, - index: usize, -} - -unsafe impl Send for User {} - -impl User { - pub fn uninitialized() -> Self { - let storage = Arc::new(Storage { - user: UnsafeCell::new(StdUser::<[T]>::uninitialized(1)), - bitmap: OptionalBitmap::none(), - }); - let user = unsafe { &mut *storage.user.get() }; - let user_ref = &mut user[0]; - Self { - user_ref, - storage, - index: 0, - } - } -} - -impl User<[T]> { - pub fn uninitialized(n: usize) -> Self { - let storage = Arc::new(Storage { - user: UnsafeCell::new(StdUser::<[T]>::uninitialized(n)), - bitmap: OptionalBitmap::none(), - }); - let user = unsafe { &mut *storage.user.get() }; - let user_ref = &mut user[..]; - Self { - user_ref, - storage, - index: 0, - } - } -} - -impl Drop for User { - fn drop(&mut self) { - self.storage.bitmap.unset(self.index); - } -} - -impl Deref for User { - type Target = UserRef; - - fn deref(&self) -> &Self::Target { - self.user_ref - } -} - -impl DerefMut for User { - fn deref_mut(&mut self) -> &mut Self::Target { - self.user_ref - } -} - -pub struct Slab(Arc>); - -impl Slab { - pub fn new(count: usize) -> Self { - assert!(count.is_power_of_two() && count >= MIN_COUNT && count <= MAX_COUNT); - Slab(Arc::new(Storage { - user: UnsafeCell::new(StdUser::<[T]>::uninitialized(count)), - bitmap: OptionalBitmap::new(count), - })) - } -} - -impl SlabAllocator for Slab { - type Output = User; - - fn alloc(&self) -> Option { - let index = self.0.bitmap.reserve()?; - let user = unsafe { &mut *self.0.user.get() }; - let user_ref = &mut user[index]; - Some(User { - user_ref, - storage: self.0.clone(), - index, - }) - } - - fn count(&self) -> usize { - let user = unsafe { &*self.0.user.get() }; - user.len() - } - - fn total_size(&self) -> usize { - let user = unsafe { &*self.0.user.get() }; - user.len() * mem::size_of::() - } -} diff --git a/async-usercalls/src/alloc/tests.rs b/async-usercalls/src/alloc/tests.rs deleted file mode 100644 index 0d9906ab..00000000 --- a/async-usercalls/src/alloc/tests.rs +++ /dev/null @@ -1,263 +0,0 @@ -use super::allocator::SharedAllocator; -use super::bitmap::*; -use super::slab::{BufSlab, Slab, SlabAllocator, User}; -use crossbeam_channel as mpmc; -use std::collections::HashSet; -use std::os::fortanix_sgx::usercalls::raw::ByteBuffer; -use std::sync::atomic::*; -use std::sync::Arc; -use std::thread; -use std::time::Instant; - -// Copied from Rust tests (test/ui/mpsc_stress.rs) -struct Barrier { - // Not using mutex/condvar for precision - shared: Arc, - count: usize, -} - -impl Barrier { - fn new(count: usize) -> Vec { - let shared = Arc::new(AtomicUsize::new(0)); - (0..count) - .map(|_| Barrier { - shared: shared.clone(), - count: count, - }) - .collect() - } - - /// Returns when `count` threads enter `wait` - fn wait(self) { - self.shared.fetch_add(1, Ordering::SeqCst); - while self.shared.load(Ordering::SeqCst) != self.count {} - } -} - -#[test] -fn bitmap() { - const BITS: usize = 1024; - let bitmap = OptionalBitmap::new(BITS); - for _ in 0..BITS { - assert!(bitmap.reserve().is_some()); - } - let mut indices = vec![34, 7, 5, 6, 120, 121, 122, 127, 0, 9] - .into_iter() - .collect::>(); - for &i in indices.iter() { - bitmap.unset(i); - } - while let Some(index) = bitmap.reserve() { - assert!(indices.remove(&index)); - } - assert!(indices.is_empty()); -} - -#[test] -fn bitmap_concurrent_use() { - const BITS: usize = 16; - const THREADS: usize = 4; - let bitmap = Arc::new(OptionalBitmap::new(BITS)); - for _ in 0..BITS - THREADS { - bitmap.reserve().unwrap(); - } - let mut handles = Vec::with_capacity(THREADS); - let mut barriers = Barrier::new(THREADS); - let (tx, rx) = mpmc::unbounded(); - - for _ in 0..THREADS { - let bitmap = Arc::clone(&bitmap); - let barrier = barriers.pop().unwrap(); - let tx = tx.clone(); - - handles.push(thread::spawn(move || { - barrier.wait(); - let index = bitmap.reserve().unwrap(); - tx.send(index).unwrap(); - })); - } - drop(tx); - for x in rx.iter() { - bitmap.unset(x); - } - for h in handles { - h.join().unwrap(); - } -} - -#[test] -fn buf_slab() { - const COUNT: usize = 16; - const SIZE: usize = 64; - let buf_slab = BufSlab::new(COUNT, SIZE); - - let bufs = (0..COUNT) - .map(|_| { - let buf = buf_slab.alloc().unwrap(); - assert!(buf.len() == SIZE); - buf - }) - .collect::>(); - - assert!(buf_slab.alloc().is_none()); - drop(bufs); - assert!(buf_slab.alloc().is_some()); -} - -#[test] -fn byte_buffer_slab() { - const COUNT: usize = 256; - let slab = Slab::::new(COUNT); - - let bufs = (0..COUNT) - .map(|_| slab.alloc().unwrap()) - .collect::>>(); - - assert!(slab.alloc().is_none()); - drop(bufs); - assert!(slab.alloc().is_some()); -} - -#[test] -fn user_is_send() { - const COUNT: usize = 16; - const SIZE: usize = 1024; - let buf_slab = BufSlab::new(COUNT, SIZE); - - let mut user = buf_slab.alloc().unwrap(); - - let h = thread::spawn(move || { - user[0..5].copy_from_enclave(b"hello"); - }); - - h.join().unwrap(); -} - -fn slab_speed(count: usize) { - let t0 = Instant::now(); - const SIZE: usize = 32; - const N: u32 = 100_000; - let buf_slab = BufSlab::new(count, SIZE); - - let bufs = (0..count - 1).map(|_| buf_slab.alloc().unwrap()).collect::>(); - - let mut x = 0; - for _ in 0..N { - let b = buf_slab.alloc().unwrap(); - x += b.len(); - } - drop(bufs); - drop(buf_slab); - let d = t0.elapsed(); - assert!(x > 0); // prevent the compiler from removing the whole loop above in release mode - println!("count = {} took {:?}", count, d / N); -} - -#[test] -#[ignore] -fn speed_slab() { - println!("\n"); - for i in 3..=16 { - slab_speed(1 << i); - } -} - -#[test] -#[ignore] -fn speed_direct() { - use std::os::fortanix_sgx::usercalls::alloc::User; - - let t0 = Instant::now(); - const SIZE: usize = 32; - const N: u32 = 100_000; - let mut x = 0; - for _ in 0..N { - let b = User::<[u8]>::uninitialized(SIZE); - x += b.len(); - } - let d = t0.elapsed(); - assert!(x > 0); - println!("took {:?}", d / N); -} - -#[test] -fn shared_allocator() { - let a = SharedAllocator::new( - [ - /*32:*/ 2048, /*64:*/ 1024, /*128:*/ 512, /*256:*/ 256, /*512:*/ 128, - /*1K:*/ 64, /*2K:*/ 0, /*4K:*/ 0, /*8K:*/ 0, /*16K:*/ 0, /*32K:*/ 0, - /*64K:*/ 1024, - ], - 1024, - ); - for size in 1..=32 { - let b = a.alloc_buf(size).unwrap(); - assert!(b.len() == 32); - } - for size in 33..=64 { - let b = a.alloc_buf(size).unwrap(); - assert!(b.len() == 64); - } - for &size in &[65, 79, 83, 120, 127, 128] { - let b = a.alloc_buf(size).unwrap(); - assert!(b.len() == 128); - } - for &size in &[129, 199, 210, 250, 255, 256] { - let b = a.alloc_buf(size).unwrap(); - assert!(b.len() == 256); - } - for &size in &[257, 299, 365, 500, 512] { - let b = a.alloc_buf(size).unwrap(); - assert!(b.len() == 512); - } - for &size in &[513, 768, 1023, 1024] { - let b = a.alloc_buf(size).unwrap(); - assert!(b.len() == 1024); - } - for i in 2..=32 { - assert!(a.alloc_buf(i * 1024).is_none()); - } - for i in 33..=64 { - let b = a.alloc_buf(i * 1024).unwrap(); - assert!(b.len() == 64 * 1024); - } -} - -fn alloc_speed(count: usize) { - let t0 = Instant::now(); - const SIZE: usize = 32; - const N: u32 = 100_000; - - let bufs = (0..count - 1).map(|_| super::alloc_buf(SIZE)).collect::>(); - - let mut x = 0; - for _ in 0..N { - let b = super::alloc_buf(SIZE); - x += b.len(); - } - drop(bufs); - let d = t0.elapsed(); - assert!(x > 0); - println!("count = {} took {:?}", count, d / N); -} - -#[test] -#[ignore] -fn speed_overall() { - println!("\n"); - for i in 3..=14 { - alloc_speed(1 << i); - } -} - -#[test] -fn alloc_buf_size() { - let b = super::alloc_buf(32); - assert_eq!(b.len(), 32); - let b = super::alloc_buf(128); - assert_eq!(b.len(), 128); - let b = super::alloc_buf(900); - assert_eq!(b.len(), 1024); - let b = super::alloc_buf(8 * 1024); - assert_eq!(b.len(), 8 * 1024); -} diff --git a/async-usercalls/src/hacks/mod.rs b/async-usercalls/src/hacks/mod.rs index f04f3655..71c0639f 100644 --- a/async-usercalls/src/hacks/mod.rs +++ b/async-usercalls/src/hacks/mod.rs @@ -1,5 +1,5 @@ use std::ops::{Deref, DerefMut}; -use std::os::fortanix_sgx::usercalls::alloc::UserSafeSized; +use std::os::fortanix_sgx::usercalls::alloc::{User, UserSafeSized}; use std::os::fortanix_sgx::usercalls::raw::ByteBuffer; mod async_queues; @@ -58,4 +58,5 @@ impl DerefMut for MakeSend { } unsafe impl Send for MakeSend {} -unsafe impl Send for MakeSend> {} +unsafe impl Send for MakeSend> {} +unsafe impl Send for MakeSend> {} diff --git a/async-usercalls/src/io_bufs.rs b/async-usercalls/src/io_bufs.rs index 7eb6b6e0..825a7a8a 100644 --- a/async-usercalls/src/io_bufs.rs +++ b/async-usercalls/src/io_bufs.rs @@ -1,9 +1,8 @@ -use crate::alloc::User; use std::cell::UnsafeCell; use std::cmp; use std::io::IoSlice; use std::ops::{Deref, DerefMut, Range}; -use std::os::fortanix_sgx::usercalls::alloc::UserRef; +use std::os::fortanix_sgx::usercalls::alloc::{User, UserRef}; use std::sync::Arc; pub struct UserBuf(UserBufKind); diff --git a/async-usercalls/src/lib.rs b/async-usercalls/src/lib.rs index ab2b9e01..0c51d29a 100644 --- a/async-usercalls/src/lib.rs +++ b/async-usercalls/src/lib.rs @@ -10,7 +10,6 @@ use std::panic; use std::sync::Mutex; use std::time::Duration; -mod alloc; mod batch_drop; mod callback; mod duplicated; @@ -23,7 +22,6 @@ mod raw; #[cfg(test)] mod tests; -pub use self::alloc::{alloc_buf, alloc_byte_buffer, User, UserSafeExt}; pub use self::batch_drop::batch_drop; pub use self::callback::CbFn; pub use self::io_bufs::{ReadBuffer, UserBuf, WriteBuffer}; diff --git a/async-usercalls/src/provider_api.rs b/async-usercalls/src/provider_api.rs index 0dff9f7f..234dbddb 100644 --- a/async-usercalls/src/provider_api.rs +++ b/async-usercalls/src/provider_api.rs @@ -1,4 +1,3 @@ -use crate::alloc::{alloc_buf, alloc_byte_buffer, User}; use crate::batch_drop; use crate::hacks::{new_std_listener, new_std_stream, MakeSend}; use crate::io_bufs::UserBuf; @@ -8,7 +7,7 @@ use fortanix_sgx_abi::Fd; use std::io; use std::mem::{self, ManuallyDrop}; use std::net::{TcpListener, TcpStream}; -use std::os::fortanix_sgx::usercalls::alloc::{User as StdUser, UserRef, UserSafe}; +use std::os::fortanix_sgx::usercalls::alloc::{User, UserRef, UserSafe}; use std::os::fortanix_sgx::usercalls::raw::ByteBuffer; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -24,11 +23,11 @@ impl AsyncUsercallProvider { where F: FnOnce(io::Result, User<[u8]>) + Send + 'static, { - let mut read_buf = ManuallyDrop::new(read_buf); + let mut read_buf = ManuallyDrop::new(MakeSend::new(read_buf)); let ptr = read_buf.as_mut_ptr(); let len = read_buf.len(); let cb = move |res: io::Result| { - let read_buf = ManuallyDrop::into_inner(read_buf); + let read_buf = ManuallyDrop::into_inner(read_buf).into_inner(); callback(res, read_buf); }; unsafe { self.raw_read(fd, ptr, len, Some(cb.into())) } @@ -93,8 +92,8 @@ impl AsyncUsercallProvider { where F: FnOnce(io::Result) + Send + 'static, { - let mut addr_buf = ManuallyDrop::new(alloc_buf(addr.len())); - let mut local_addr = ManuallyDrop::new(MakeSend::new(alloc_byte_buffer())); + let mut addr_buf = ManuallyDrop::new(MakeSend::new(User::<[u8]>::uninitialized(addr.len()))); + let mut local_addr = ManuallyDrop::new(MakeSend::new(User::::uninitialized())); addr_buf[0..addr.len()].copy_from_enclave(addr.as_bytes()); let addr_buf_ptr = addr_buf.as_raw_mut_ptr() as *mut u8; @@ -121,8 +120,8 @@ impl AsyncUsercallProvider { where F: FnOnce(io::Result) + Send + 'static, { - let mut local_addr = ManuallyDrop::new(MakeSend::new(alloc_byte_buffer())); - let mut peer_addr = ManuallyDrop::new(MakeSend::new(alloc_byte_buffer())); + let mut local_addr = ManuallyDrop::new(MakeSend::new(User::::uninitialized())); + let mut peer_addr = ManuallyDrop::new(MakeSend::new(User::::uninitialized())); let local_addr_ptr = local_addr.as_raw_mut_ptr(); let peer_addr_ptr = peer_addr.as_raw_mut_ptr(); @@ -149,9 +148,9 @@ impl AsyncUsercallProvider { where F: FnOnce(io::Result) + Send + 'static, { - let mut addr_buf = ManuallyDrop::new(alloc_buf(addr.len())); - let mut local_addr = ManuallyDrop::new(MakeSend::new(alloc_byte_buffer())); - let mut peer_addr = ManuallyDrop::new(MakeSend::new(alloc_byte_buffer())); + let mut addr_buf = ManuallyDrop::new(MakeSend::new(User::<[u8]>::uninitialized(addr.len()))); + let mut local_addr = ManuallyDrop::new(MakeSend::new(User::::uninitialized())); + let mut peer_addr = ManuallyDrop::new(MakeSend::new(User::::uninitialized())); addr_buf[0..addr.len()].copy_from_enclave(addr.as_bytes()); let addr_buf_ptr = addr_buf.as_raw_mut_ptr() as *mut u8; @@ -180,10 +179,10 @@ impl AsyncUsercallProvider { pub fn alloc(&self, callback: F) where T: UserSafe, - F: FnOnce(io::Result>) + Send + 'static, + F: FnOnce(io::Result>) + Send + 'static, { let cb = move |res: io::Result<*mut u8>| { - let res = res.map(|ptr| unsafe { StdUser::::from_raw(ptr as _) }); + let res = res.map(|ptr| unsafe { User::::from_raw(ptr as _) }); callback(res); }; unsafe { @@ -200,10 +199,10 @@ impl AsyncUsercallProvider { pub fn alloc_slice(&self, len: usize, callback: F) where [T]: UserSafe, - F: FnOnce(io::Result>) + Send + 'static, + F: FnOnce(io::Result>) + Send + 'static, { let cb = move |res: io::Result<*mut u8>| { - let res = res.map(|ptr| unsafe { StdUser::<[T]>::from_raw_parts(ptr as _, len) }); + let res = res.map(|ptr| unsafe { User::<[T]>::from_raw_parts(ptr as _, len) }); callback(res); }; unsafe { @@ -217,7 +216,7 @@ impl AsyncUsercallProvider { /// /// Please refer to the type-level documentation for general notes about /// callbacks. - pub fn free(&self, mut buf: StdUser, callback: Option) + pub fn free(&self, mut buf: User, callback: Option) where T: ?Sized + UserSafe, F: FnOnce() + Send + 'static, @@ -263,7 +262,7 @@ fn copy_user_buffer(buf: &UserRef) -> Vec { unsafe { let buf = buf.to_enclave(); if buf.len > 0 { - let user = StdUser::from_raw_parts(buf.data as _, buf.len); + let user = User::from_raw_parts(buf.data as _, buf.len); let v = user.to_enclave(); batch_drop(user); v diff --git a/async-usercalls/src/tests.rs b/async-usercalls/src/tests.rs index 406c8244..2bdc473b 100644 --- a/async-usercalls/src/tests.rs +++ b/async-usercalls/src/tests.rs @@ -5,7 +5,7 @@ use std::io; use std::net::{TcpListener, TcpStream}; use std::ops::Deref; use std::os::fortanix_sgx::io::AsRawFd; -use std::os::fortanix_sgx::usercalls::alloc::User as StdUser; +use std::os::fortanix_sgx::usercalls::alloc::User; use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering}; use std::sync::Arc; use std::thread; @@ -192,12 +192,10 @@ fn safe_alloc_free() { rx.recv().unwrap(); } -unsafe impl Send for MakeSend> {} - #[test] fn write_buffer_basic() { const LENGTH: usize = 1024; - let mut write_buffer = WriteBuffer::new(super::alloc_buf(1024)); + let mut write_buffer = WriteBuffer::new(User::<[u8]>::uninitialized(1024)); let buf = vec![0u8; LENGTH]; assert_eq!(write_buffer.write(&buf), LENGTH); @@ -213,7 +211,7 @@ fn write_buffer_basic() { #[should_panic] fn call_consumable_chunk_twice() { const LENGTH: usize = 1024; - let mut write_buffer = WriteBuffer::new(super::alloc_buf(1024)); + let mut write_buffer = WriteBuffer::new(User::<[u8]>::uninitialized(1024)); let buf = vec![0u8; LENGTH]; assert_eq!(write_buffer.write(&buf), LENGTH); @@ -228,19 +226,19 @@ fn call_consumable_chunk_twice() { #[should_panic] fn consume_wrong_buf() { const LENGTH: usize = 1024; - let mut write_buffer = WriteBuffer::new(super::alloc_buf(1024)); + let mut write_buffer = WriteBuffer::new(User::<[u8]>::uninitialized(1024)); let buf = vec![0u8; LENGTH]; assert_eq!(write_buffer.write(&buf), LENGTH); assert_eq!(write_buffer.write(&buf), 0); - let unrelated_buf: UserBuf = super::alloc_buf(512).into(); + let unrelated_buf: UserBuf = User::<[u8]>::uninitialized(512).into(); write_buffer.consume(unrelated_buf, 100); } #[test] fn read_buffer_basic() { - let mut buf = super::alloc_buf(64); + let mut buf = User::<[u8]>::uninitialized(64); const DATA: &'static [u8] = b"hello"; buf[0..DATA.len()].copy_from_enclave(DATA); @@ -293,7 +291,8 @@ impl FnOnce<(io::Result,)> for KeepAccepting { read: true, provider: self.provider.clone(), }; - self.provider.read(fd, alloc_buf(Echo::READ_BUF_SIZE), cb); + self.provider + .read(fd, User::<[u8]>::uninitialized(Echo::READ_BUF_SIZE), cb); } let provider = Arc::clone(&self.provider); provider.accept_stream(self.listener.as_raw_fd(), self); @@ -345,7 +344,11 @@ impl FnOnce<(io::Result, UserBuf)> for Echo { Ok(len) if len > 0 => { self.read = true; let provider = Arc::clone(&self.provider); - provider.read(self.stream.as_raw_fd(), alloc_buf(Echo::READ_BUF_SIZE), self); + provider.read( + self.stream.as_raw_fd(), + User::<[u8]>::uninitialized(Echo::READ_BUF_SIZE), + self, + ); } _ => self.close(), }