Skip to content

Commit

Permalink
Add twizzler crate stubs.
Browse files Browse the repository at this point in the history
  • Loading branch information
dbittman committed Dec 18, 2024
1 parent 2276f11 commit 8c121c4
Show file tree
Hide file tree
Showing 21 changed files with 483 additions and 84 deletions.
178 changes: 104 additions & 74 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ members = [
"src/lib/twizzler-futures",
"src/lib/dynlink",
"src/lib/secgate",
"src/lib/twizzler",
"src/rt/monitor",
"src/rt/monitor-api",
"src/rt/monitor/tests/montest",
Expand Down
16 changes: 6 additions & 10 deletions src/lib/twizzler-abi/src/syscall/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,35 +43,31 @@ impl ObjectSource {
}
}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Default)]
#[repr(C)]
/// The backing memory type for this object. Currently doesn't do anything.
pub enum BackingType {
/// The default, let the kernel decide based on the [LifetimeType] of the object.
#[default]
Normal = 0,
}

impl Default for BackingType {
fn default() -> Self {
Self::Normal
}
}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Default)]
#[repr(C)]
/// The base lifetime type of the object. Note that this does not ensure that the object is stored
/// in a specific type of memory, the kernel is allowed to migrate objects with the Normal
/// [BackingType] as it sees fit. For more information on object lifetime, see [the book](https://twizzler-operating-system.github.io/nightly/book/object_lifetime.html).
pub enum LifetimeType {
/// This object is volatile, and is expected to be deleted after a power cycle.
#[default]
Volatile = 0,
/// This object is persistent, and should be deleted only after an explicit delete call.
Persistent = 1,
}

bitflags! {
/// Flags to pass to the object create system call.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct ObjectCreateFlags: u32 {
}
}
Expand All @@ -83,7 +79,7 @@ bitflags! {
}
}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Default)]
#[repr(C)]
/// Full object creation specification, minus ties.
pub struct ObjectCreate {
Expand Down
10 changes: 10 additions & 0 deletions src/lib/twizzler/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "twizzler"
version = "0.99.0"
edition = "2021"

[dependencies]
bitflags = "2"
thiserror = "2"
twizzler-rt-abi = { path = "../../abi/rt-abi" }
twizzler-abi = { path = "../../lib/twizzler-abi" }
4 changes: 4 additions & 0 deletions src/lib/twizzler/src/alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod arena;
pub mod invbox;

pub trait Allocator {}
14 changes: 14 additions & 0 deletions src/lib/twizzler/src/alloc/arena.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use super::Allocator;
use crate::object::Object;

pub struct ArenaAllocator {
obj: Object<ArenaBase>,
}

#[repr(C)]
pub struct ArenaBase {}

#[repr(C)]
pub struct ArenaObjBase {}

impl Allocator for ArenaAllocator {}
5 changes: 5 additions & 0 deletions src/lib/twizzler/src/alloc/invbox.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use crate::{marker::Invariant, ptr::InvPtr};

pub struct InvBox<T: Invariant> {
raw: InvPtr<T>,
}
1 change: 1 addition & 0 deletions src/lib/twizzler/src/collections.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod vec;
Empty file.
11 changes: 11 additions & 0 deletions src/lib/twizzler/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![feature(negative_impls)]
#![feature(auto_traits)]
#![feature(strict_provenance)]
#![feature(allocator_api)]

pub mod alloc;
pub mod collections;
pub mod marker;
pub mod object;
pub mod ptr;
pub mod tx;
58 changes: 58 additions & 0 deletions src/lib/twizzler/src/marker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//! Marker types for invariance, store side-effects, and base types.
/// Indicates that a type is _invariant_ and thus can be stored in an object.
///
/// # Safety
/// The implementation must ensure that the type is invariant, meaning that the type must:
/// - Be FFI safe.
/// - Be stable in-memory (independent of architecture). This means, among other things, that the
/// type must be fixed-width. For example, usize is not `Invariant`.
pub unsafe trait Invariant {}

unsafe impl Invariant for u8 {}
unsafe impl Invariant for u16 {}
unsafe impl Invariant for u32 {}
unsafe impl Invariant for u64 {}
unsafe impl Invariant for bool {}
unsafe impl Invariant for i8 {}
unsafe impl Invariant for i16 {}
unsafe impl Invariant for i32 {}
unsafe impl Invariant for i64 {}

unsafe impl Invariant for f64 {}
unsafe impl Invariant for f32 {}

unsafe impl Invariant for () {}

unsafe impl<T: Invariant, const N: usize> Invariant for [T; N] {}

unsafe impl<T: Invariant> Invariant for (T,) {}

unsafe impl<T: Invariant> Invariant for Option<T> {}
unsafe impl<R: Invariant, E: Invariant> Invariant for Result<R, E> {}

/// The type may move between objects without side effects. Notably, this is
/// not implemented for invariant pointers or types that contain them, since an invariant pointer
/// may reference an object's Foreign Object Table. This is a little restrictive (technically
/// intra-object pointers are safe to move intra-object), but it's the best we can do at
/// compile-time.
///
/// # Safety
/// The implementation must ensure that no store side effects must occur when writing this value to
/// object memory.
pub unsafe auto trait StoreCopy {}

/// A zero-sized phantom marker for indicating that the containing type has a side effect when
/// storing (e.g. it has an invariant pointer).
#[derive(Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, Debug)]
pub struct PhantomStoreEffect;

impl !StoreCopy for PhantomStoreEffect {}
impl !Unpin for PhantomStoreEffect {}

pub trait BaseType {
/// The fingerprint of this type.
fn fingerprint() -> u64 {
0
}
}
115 changes: 115 additions & 0 deletions src/lib/twizzler/src/object.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//! Traits and types for working with objects.
use std::marker::PhantomData;

use fot::FotEntry;
use twizzler_abi::{
meta::MetaInfo,
object::{ObjID, MAX_SIZE, NULLPAGE_SIZE},
};
use twizzler_rt_abi::object::ObjectHandle;

use crate::{marker::BaseType, ptr::Ref};

mod builder;
mod fot;
mod meta;

/// Operations common to structured objects.
pub trait TypedObject {
/// The base type of this object.
type Base: BaseType;

/// Returns a resolved reference to the object's base.
fn base(&self) -> Ref<'_, Self::Base>;
}

/// Operations common to all objects, with raw pointers.
pub trait RawObject {
/// Get the underlying runtime handle for this object.
fn handle(&self) -> &ObjectHandle;

/// Get the object ID.
fn id(&self) -> ObjID {
self.handle().id()
}

/// Get a const pointer to the object base.
fn base_ptr<T>(&self) -> *const T {
self.lea(NULLPAGE_SIZE, size_of::<T>()).unwrap().cast()
}

/// Get a mut pointer to the object base.
fn base_mut_ptr<T>(&self) -> *mut T {
self.lea_mut(NULLPAGE_SIZE, size_of::<T>()).unwrap().cast()
}

/// Get a const pointer to the object metadata.
fn meta_ptr(&self) -> *const MetaInfo {
self.handle().meta().cast()
}

/// Get a mut pointer to the object metadata.
fn meta_mut_ptr(&self) -> *mut MetaInfo {
self.handle().meta().cast()
}

/// Get a const pointer to a given FOT entry.
fn fote_ptr(&self, idx: usize) -> Option<*const FotEntry> {
let offset: isize = (1 + idx).try_into().ok()?;
unsafe { Some((self.meta_ptr() as *const FotEntry).offset(-offset)) }
}

/// Get a mut pointer to a given FOT entry.
fn fote_ptr_mut(&self, idx: usize) -> Option<*mut FotEntry> {
let offset: isize = (1 + idx).try_into().ok()?;
unsafe { Some((self.meta_mut_ptr() as *mut FotEntry).offset(-offset)) }
}

/// Get a const pointer to given range of the object.
fn lea(&self, offset: usize, _len: usize) -> Option<*const u8> {
Some(unsafe { self.handle().start().add(offset) as *const u8 })
}

/// Get a mut pointer to given range of the object.
fn lea_mut(&self, offset: usize, _len: usize) -> Option<*mut u8> {
Some(unsafe { self.handle().start().add(offset) as *mut u8 })
}

/// If the pointer is local to this object, return the offset into the object. Otherwise, return
/// None.
fn ptr_local(&self, ptr: *const u8) -> Option<usize> {
if ptr.addr() >= self.handle().start().addr()
&& ptr.addr() < self.handle().start().addr() + MAX_SIZE
{
Some(ptr.addr() - self.handle().start().addr())
} else {
None
}
}
}

impl RawObject for ObjectHandle {
fn handle(&self) -> &ObjectHandle {
self
}
}

pub struct Object<Base> {
handle: ObjectHandle,
_pd: PhantomData<*const Base>,
}

impl<Base> RawObject for Object<Base> {
fn handle(&self) -> &ObjectHandle {
&self.handle
}
}

impl<Base: BaseType> TypedObject for Object<Base> {
type Base = Base;

fn base(&self) -> Ref<'_, Self::Base> {
todo!()
}
}
53 changes: 53 additions & 0 deletions src/lib/twizzler/src/object/builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use std::{alloc::AllocError, marker::PhantomData, mem::MaybeUninit};

use thiserror::Error;
use twizzler_abi::syscall::{ObjectCreate, ObjectCreateError};
use twizzler_rt_abi::object::{MapError, ObjectHandle};

use super::RawObject;
use crate::marker::BaseType;

#[derive(Clone, Copy, Debug, Error)]
/// Possible errors from creating an object.
pub enum CreateError {
#[error(transparent)]
Create(#[from] ObjectCreateError),
#[error(transparent)]
Map(#[from] MapError),
#[error(transparent)]
Alloc(#[from] AllocError),
}

/// An object builder, for constructing objects using a builder API.
pub struct ObjectBuilder<Base: BaseType> {
spec: ObjectCreate,
_pd: PhantomData<Base>,
}

impl<Base: BaseType> ObjectBuilder<Base> {
/// Make a new object builder.
pub fn new(spec: ObjectCreate) -> Self {
Self {
spec,
_pd: PhantomData,
}
}
}

impl<Base: BaseType> Default for ObjectBuilder<Base> {
fn default() -> Self {
Self::new(ObjectCreate::default())
}
}

/// An uninitialized object, used during object construction.
pub struct UninitObject<T> {
handle: ObjectHandle,
_pd: PhantomData<*mut MaybeUninit<T>>,
}

impl<T> RawObject for UninitObject<T> {
fn handle(&self) -> &ObjectHandle {
&self.handle
}
}
34 changes: 34 additions & 0 deletions src/lib/twizzler/src/object/fot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::sync::atomic::AtomicU32;

use thiserror::Error;

bitflags::bitflags! {
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub struct FotFlags : u32 {
const RESERVED = 1;
const ACTIVE = 2;
const RESOLVER = 4;
}
}

pub type ResolverFn = extern "C" fn(ResolveRequest) -> Result<FotResolve, FotError>;

#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Error)]
pub enum FotError {
#[error("invalid FOT index")]
InvalidIndex,
#[error("invalid FOT entry")]
InvalidFotEntry,
}

pub struct ResolveRequest {}

pub struct FotResolve {}

#[repr(C)]
pub struct FotEntry {
pub values: [u64; 2],
pub resolver: u64,
pub flags: AtomicU32,
}
1 change: 1 addition & 0 deletions src/lib/twizzler/src/object/meta.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub use twizzler_abi::meta::*;
7 changes: 7 additions & 0 deletions src/lib/twizzler/src/ptr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod global;
mod invariant;
mod resolved;

pub use global::*;
pub use invariant::*;
pub use resolved::*;
11 changes: 11 additions & 0 deletions src/lib/twizzler/src/ptr/global.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use std::marker::PhantomData;

use twizzler_abi::object::ObjID;

#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Ord, Eq, Hash)]
/// A global pointer, containing a fully qualified object ID and offset.
pub struct GlobalPtr<T> {
id: ObjID,
offset: usize,
_pd: PhantomData<*const T>,
}
Loading

0 comments on commit 8c121c4

Please sign in to comment.