From 7a5e08eb940f2c6ace0c046cb05d5562e8898b52 Mon Sep 17 00:00:00 2001 From: Daniel Bittman Date: Fri, 10 Jan 2025 13:04:59 -0800 Subject: [PATCH] Simple vec push and get working. --- src/bin/init/src/main.rs | 6 +- src/kernel/src/main.rs | 2 +- src/lib/twizzler/src/collections/vec.rs | 76 +++++++++---------- src/lib/twizzler/src/ptr/resolved.rs | 20 +++++ src/lib/twizzler/src/tx.rs | 31 ++++---- src/lib/twizzler/src/tx/object.rs | 9 ++- src/rt/reference/src/runtime/object.rs | 2 - .../src/runtime/object/handlecache.rs | 2 +- 8 files changed, 84 insertions(+), 64 deletions(-) diff --git a/src/bin/init/src/main.rs b/src/bin/init/src/main.rs index cd69b1da4..00416fd76 100644 --- a/src/bin/init/src/main.rs +++ b/src/bin/init/src/main.rs @@ -108,7 +108,7 @@ fn main() { .unwrap(); debug!("device manager is up!"); - //initialize_pager(); + initialize_pager(); std::mem::forget(dev_comp); run_tests("test_bins", false); @@ -170,10 +170,6 @@ fn run_tests(test_list_name: &str, benches: bool) { let str = String::from_utf8(bytes.to_vec()).unwrap(); let mut test_failed = false; for line in str.split("\n").filter(|l| !l.is_empty()) { - if !line.starts_with("twizzler-") { - println!("skipping test {}", line); - continue; - } println!("STARTING TEST {}", line); let test_comp = monitor_api::CompartmentLoader::new( line, diff --git a/src/kernel/src/main.rs b/src/kernel/src/main.rs index 8c5545802..da291e387 100755 --- a/src/kernel/src/main.rs +++ b/src/kernel/src/main.rs @@ -157,7 +157,7 @@ pub fn idle_main() -> ! { start_entropy_contribution_thread(); #[cfg(test)] - if is_test_mode() && false { + if is_test_mode() { // Run tests on a high priority thread, so any threads spawned by tests // don't preempt the testing thread. crate::thread::entry::run_closure_in_new_thread( diff --git a/src/lib/twizzler/src/collections/vec.rs b/src/lib/twizzler/src/collections/vec.rs index 1ff1ce457..5b0901343 100644 --- a/src/lib/twizzler/src/collections/vec.rs +++ b/src/lib/twizzler/src/collections/vec.rs @@ -1,13 +1,9 @@ use std::{ alloc::{AllocError, Layout}, mem::MaybeUninit, - ops::{Index, IndexMut}, }; -use twizzler_abi::{ - klog_println, - object::{MAX_SIZE, NULLPAGE_SIZE}, -}; +use twizzler_abi::object::{MAX_SIZE, NULLPAGE_SIZE}; use crate::{ alloc::{Allocator, SingleObjectAllocator}, @@ -27,6 +23,7 @@ impl VecInner { fn do_realloc( &mut self, newcap: usize, + newlen: usize, alloc: &Alloc, tx: &TxObject<()>, ) -> crate::tx::Result> { @@ -37,22 +34,13 @@ impl VecInner { let new_layout = Layout::array::(newcap).map_err(|_| AllocError)?; let old_layout = Layout::array::(self.cap).map_err(|_| AllocError)?; - klog_println!("rea: {:?} {:?}", old_layout, new_layout); - klog_println!("resolve global"); let old_global = self.start.global().cast(); - klog_println!("realloc_tx"); let new_alloc = alloc.realloc_tx(old_global, old_layout, new_layout.size(), tx)?; - klog_println!("set"); self.start = InvPtr::new(tx, new_alloc.cast())?; - klog_println!( - "invptr set to: {} {} .. {:p}", - self.start.fot_index(), - self.start.offset(), - self - ); self.cap = newcap; + self.len = newlen; Ok(unsafe { new_alloc.cast::().resolve().owned().mutable() }) } @@ -74,10 +62,8 @@ impl Allocator for VecObjectAlloc { if layout.size() > MAX_SIZE - NULLPAGE_SIZE * 4 { return Err(std::alloc::AllocError); } - klog_println!("getting object handle"); let obj = twizzler_rt_abi::object::twz_rt_get_object_handle((self as *const Self).cast()) .unwrap(); - klog_println!("got it!"); Ok(GlobalPtr::new(obj.id(), (NULLPAGE_SIZE * 2) as u64)) } @@ -113,7 +99,8 @@ impl Vec { fn get_slice_grow( &self, tx: impl AsRef, - ) -> crate::tx::Result>> { + ) -> crate::tx::Result>> { + let oldlen = self.inner.len; if self.inner.len == self.inner.cap { if self.inner.start.raw() as usize + size_of::() * self.inner.cap >= MAX_SIZE - NULLPAGE_SIZE @@ -122,30 +109,31 @@ impl Vec { } let newcap = std::cmp::max(self.inner.cap, 1) * 2; let inner = self.inner.get_mut(tx.as_ref())?; - let r = inner.do_realloc(newcap, &self.alloc, tx.as_ref())?; - Ok(Self::maybe_uninit_slice(r, newcap)) + let r = inner.do_realloc(newcap, oldlen + 1, &self.alloc, tx.as_ref())?; + Ok(Self::maybe_uninit_slice(r, newcap) + .get_mut(oldlen) + .unwrap() + .owned()) } else { + self.inner.get_mut(tx.as_ref())?.len += 1; Ok(Self::maybe_uninit_slice( unsafe { self.inner.start.resolve().mutable() }, self.inner.cap, - )) + ) + .get_mut(oldlen) + .unwrap() + .owned()) } } fn do_push(&self, item: T, tx: impl AsRef) -> crate::tx::Result<()> { - klog_println!("do_push: 0"); let mut r = self.get_slice_grow(&tx)?; - klog_println!("do_push: 2"); - // write item, tracking in tx - tx.as_ref().write_uninit(&mut r[self.inner.len], item)?; - klog_println!("do_push: 3"); - self.inner.get_mut(tx.as_ref())?.len += 1; - klog_println!("do_push: x"); + tx.as_ref().write_uninit(&mut *r, item)?; Ok(()) } - fn len(&self) -> usize { + pub fn len(&self) -> usize { self.inner.len } } @@ -169,9 +157,8 @@ impl Vec { where F: FnOnce(TxRef>) -> crate::tx::Result>, { - let mut slice = self.get_slice_grow(&tx)?; - let ptr = &mut slice.as_slice_mut()[self.inner.len]; - let txref = unsafe { TxRef::new(tx, ptr) }; + let mut r = self.get_slice_grow(&tx)?; + let txref = unsafe { TxRef::new(tx, &mut *r) }; let val = ctor(txref)?; val.into_tx().commit()?; Ok(()) @@ -213,26 +200,24 @@ mod tests { #[test] fn simple_push() { - twizzler_abi::klog_println!("A"); let vobj = ObjectBuilder::default() .build_inplace(|tx| tx.write(Vec::new_in(VecObjectAlloc))) .unwrap(); - twizzler_abi::klog_println!("B"); let tx = vobj.tx().unwrap(); - twizzler_abi::klog_println!("B1"); tx.base().push(Simple { x: 42 }, &tx).unwrap(); - twizzler_abi::klog_println!("B2"); + tx.base().push(Simple { x: 43 }, &tx).unwrap(); let vobj = tx.commit().unwrap(); - twizzler_abi::klog_println!("C: {}", vobj.base().len()); let base = vobj.base(); + assert_eq!(base.len(), 2); let item = base.get(0).unwrap(); assert_eq!(item.x, 42); - twizzler_abi::klog_println!("Z"); + let item2 = base.get(1).unwrap(); + assert_eq!(item2.x, 43); } - //#[test] + #[test] fn simple_push_vo() { let mut vec_obj = VecObject::new(ObjectBuilder::default()).unwrap(); vec_obj.push(Simple { x: 42 }).unwrap(); @@ -241,6 +226,19 @@ mod tests { assert_eq!(item.x, 42); } + #[test] + fn many_push_vo() { + let mut vec_obj = VecObject::new(ObjectBuilder::default()).unwrap(); + for i in 0..100 { + vec_obj.push(Simple { x: i * i }).unwrap(); + } + + for i in 0..100 { + let item = vec_obj.get(i as usize).unwrap(); + assert_eq!(item.x, i * i); + } + } + //#[test] fn node_push() { let simple_obj = ObjectBuilder::default().build(Simple { x: 3 }).unwrap(); diff --git a/src/lib/twizzler/src/ptr/resolved.rs b/src/lib/twizzler/src/ptr/resolved.rs index 4d793536f..c06a44e73 100644 --- a/src/lib/twizzler/src/ptr/resolved.rs +++ b/src/lib/twizzler/src/ptr/resolved.rs @@ -100,6 +100,7 @@ impl<'a, T> Drop for Ref<'a, T> { pub struct RefMut<'obj, T> { ptr: *mut T, handle: *const ObjectHandle, + owned: bool, _pd: PhantomData<&'obj mut T>, } @@ -112,6 +113,7 @@ impl<'obj, T> RefMut<'obj, T> { Self { ptr, handle, + owned: false, _pd: PhantomData, } } @@ -120,6 +122,7 @@ impl<'obj, T> RefMut<'obj, T> { RefMut { ptr: self.ptr.cast(), handle: self.handle, + owned: self.owned, _pd: PhantomData, } } @@ -135,6 +138,15 @@ impl<'obj, T> RefMut<'obj, T> { pub fn global(&self) -> GlobalPtr { GlobalPtr::new(self.handle().id(), self.offset()) } + + pub fn owned<'b>(&self) -> RefMut<'b, T> { + RefMut { + ptr: self.ptr, + owned: true, + handle: Box::into_raw(Box::new(self.handle().clone())), + _pd: PhantomData, + } + } } impl<'obj, T> Deref for RefMut<'obj, T> { @@ -157,6 +169,14 @@ impl<'a, T> From> for GlobalPtr { } } +impl<'a, T> Drop for RefMut<'a, T> { + fn drop(&mut self) { + if self.owned { + let _boxed = unsafe { Box::from_raw(self.handle as *mut ObjectHandle) }; + } + } +} + pub struct RefSlice<'a, T> { ptr: Ref<'a, T>, len: usize, diff --git a/src/lib/twizzler/src/tx.rs b/src/lib/twizzler/src/tx.rs index 11df32cff..549d3e136 100644 --- a/src/lib/twizzler/src/tx.rs +++ b/src/lib/twizzler/src/tx.rs @@ -3,12 +3,13 @@ mod object; mod reference; mod unsafetx; -use std::{alloc::AllocError, mem::MaybeUninit}; +use std::{alloc::AllocError, cell::UnsafeCell, mem::MaybeUninit}; pub use batch::*; pub use object::*; pub use reference::*; use twizzler_abi::klog_println; +use twizzler_rt_abi::object::MapError; pub use unsafetx::*; use crate::{ @@ -23,7 +24,6 @@ pub trait TxHandle { fn tx_mut(&self, data: *const u8, len: usize) -> Result<*mut u8>; fn write_uninit(&self, target: &mut MaybeUninit, value: T) -> Result<&mut T> { - klog_println!("==> write uninit {:p}", target); let ptr = self .tx_mut((target as *mut MaybeUninit).cast(), size_of::())? .cast::>(); @@ -60,28 +60,33 @@ pub enum TxError { /// Create error #[error("create error")] CreateError(#[from] CreateError), + /// Map error + #[error("mapping error")] + MapError(#[from] MapError), } -#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] #[repr(transparent)] -pub struct TxCell(T); +pub struct TxCell(UnsafeCell); + +impl Clone for TxCell { + fn clone(&self) -> Self { + Self(UnsafeCell::new(unsafe { + self.0.get().as_ref().unwrap().clone() + })) + } +} impl TxCell { pub fn new(inner: T) -> Self { - Self(inner) + Self(UnsafeCell::new(inner)) } pub unsafe fn as_mut(&self) -> &mut T { - unsafe { - ((&self.0 as *const T) as *mut T) - .cast::() - .as_mut() - .unwrap_unchecked() - } + unsafe { self.0.get().as_mut().unwrap_unchecked() } } pub fn get_mut(&self, tx: &impl TxHandle) -> Result<&mut T> { - let inner = &self.0 as *const T; + let inner = self.0.get(); let ptr = tx.tx_mut(inner.cast(), size_of::())?; unsafe { Ok(ptr.cast::().as_mut().unwrap_unchecked()) } } @@ -91,7 +96,7 @@ impl std::ops::Deref for TxCell { type Target = T; fn deref(&self) -> &Self::Target { - &self.0 + unsafe { self.0.get().as_ref().unwrap() } } } diff --git a/src/lib/twizzler/src/tx/object.rs b/src/lib/twizzler/src/tx/object.rs index def7b4f53..dfea93690 100644 --- a/src/lib/twizzler/src/tx/object.rs +++ b/src/lib/twizzler/src/tx/object.rs @@ -1,6 +1,6 @@ use std::{marker::PhantomData, mem::MaybeUninit}; -use twizzler_rt_abi::object::ObjectHandle; +use twizzler_rt_abi::object::{MapFlags, ObjectHandle}; use super::{Result, TxHandle}; use crate::{ @@ -26,9 +26,11 @@ impl TxObject { } pub fn commit(self) -> Result> { - let this = std::hint::black_box(self); + let handle = self.handle; + let new_obj = + unsafe { Object::map_unchecked(handle.id(), MapFlags::READ | MapFlags::WRITE) }?; // TODO: commit tx - Ok(unsafe { Object::from_handle_unchecked(this.handle) }) + Ok(new_obj) } pub fn abort(self) -> Object { @@ -113,6 +115,7 @@ mod tests { let mut tx = obj.tx().unwrap(); let mut base = tx.base_mut(); base.x = 42; + drop(base); let obj = tx.commit().unwrap(); assert_eq!(obj.base().x, 42); } diff --git a/src/rt/reference/src/runtime/object.rs b/src/rt/reference/src/runtime/object.rs index d985c0a05..5035d4298 100644 --- a/src/rt/reference/src/runtime/object.rs +++ b/src/rt/reference/src/runtime/object.rs @@ -199,9 +199,7 @@ impl ObjectHandleManager { /// Get an object handle from a pointer to within that object. pub fn get_handle(&mut self, ptr: *const u8) -> Option { - tracing::info!("in get_handle"); let handle = self.cache.activate_from_ptr(ptr)?; - tracing::info!("in get_handle: done: {:p}", handle.runtime_info); let oh = ObjectHandle::from_raw(handle); let oh2 = oh.clone().into_raw(); std::mem::forget(oh); diff --git a/src/rt/reference/src/runtime/object/handlecache.rs b/src/rt/reference/src/runtime/object/handlecache.rs index e9b14daf9..cde9e4b86 100644 --- a/src/rt/reference/src/runtime/object/handlecache.rs +++ b/src/rt/reference/src/runtime/object/handlecache.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use tracing::info as trace; +use tracing::trace; use twizzler_abi::object::MAX_SIZE; use twizzler_rt_abi::bindings::object_handle;