Skip to content

Commit

Permalink
Documented.
Browse files Browse the repository at this point in the history
  • Loading branch information
dbittman committed Aug 7, 2024
1 parent d661897 commit baa93d2
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 46 deletions.
25 changes: 24 additions & 1 deletion src/lib/twizzler-abi/src/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ use core::sync::atomic::{AtomicU64, Ordering};
#[cfg(not(feature = "kernel"))]
use core::time::Duration;

use crate::marker::BaseType;
#[cfg(not(feature = "kernel"))]
use crate::syscall::*;
use crate::{
marker::BaseType,
syscall::{ThreadSyncFlags, ThreadSyncOp, ThreadSyncReference, ThreadSyncSleep},
};
#[allow(unused_imports)]
use crate::{
object::{ObjID, Protections},
Expand Down Expand Up @@ -125,6 +128,26 @@ impl ThreadRepr {
}
}

/// Create a [ThreadSyncSleep] that will wait until the thread's state matches `state`.
pub fn waitable(&self, state: ExecutionState) -> ThreadSyncSleep {
ThreadSyncSleep::new(
ThreadSyncReference::Virtual(&self.status),
state as u64,
ThreadSyncOp::Equal,
ThreadSyncFlags::empty(),
)
}

/// Create a [ThreadSyncSleep] that will wait until the thread's state is _not_ `state`.
pub fn waitable_until_not(&self, state: ExecutionState) -> ThreadSyncSleep {
ThreadSyncSleep::new(
ThreadSyncReference::Virtual(&self.status),
state as u64,
ThreadSyncOp::Equal,
ThreadSyncFlags::INVERT,
)
}

#[cfg(not(feature = "kernel"))]
/// Wait for a thread's status to change, optionally timing out. Return value is None if timeout
/// occurs, or Some((ExecutionState, code)) otherwise.
Expand Down
9 changes: 9 additions & 0 deletions src/runtime/monitor/src/mon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ pub(crate) mod compartment;
pub(crate) mod space;
pub(crate) mod thread;

/// A security monitor instance. All monitor logic is implemented as methods for this type.
/// We split the state into the following components: 'space', managing the virtual memory space and
/// mapping objects, 'thread_mgr', which manages all threads owned by the monitor (typically, all
/// threads started by compartments), 'compartments', which manages compartment state, and
/// 'dynlink', which contains the dynamic linker state. The unmapper allows for background unmapping
/// and cleanup of objects and handles.
pub struct Monitor {
space: RwLock<space::Space>,
thread_mgr: RwLock<thread::ThreadMgr>,
Expand All @@ -18,10 +24,13 @@ pub struct Monitor {

static MONITOR: OnceLock<Monitor> = OnceLock::new();

/// Get the monitor instance. Panics if called before first call to [set_monitor].
pub fn get_monitor() -> &'static Monitor {
MONITOR.get().unwrap()
}

/// Set the monitor instance. Can only be called once. Must be called before any call to
/// [get_monitor].
pub fn set_monitor(monitor: Monitor) {
if MONITOR.set(monitor).is_err() {
panic!("second call to set_monitor");
Expand Down
5 changes: 5 additions & 0 deletions src/runtime/monitor/src/mon/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ pub use handle::MapHandle;
pub use unmapper::Unmapper;

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
/// A mapping of an object and flags.
pub struct MapInfo {
pub(crate) id: ObjID,
pub(crate) flags: MapFlags,
}

#[derive(Default)]
/// An address space we can map objects into.
pub struct Space {
maps: HashMap<MapInfo, MappedObject>,
}
Expand All @@ -44,6 +46,7 @@ fn mapflags_into_prot(flags: MapFlags) -> Protections {
}

impl Space {
/// Map an object into the space.
pub fn map(&mut self, info: MapInfo) -> Result<MapHandle, MapError> {
// Can't use the entry API here because the closure may fail.
let item = match self.maps.get_mut(&info) {
Expand Down Expand Up @@ -80,6 +83,8 @@ impl Space {
Ok(Arc::new(MapHandleInner::new(info, item.addrs)))
}

/// Remove an object from the space. The actual unmapping syscall only happens once the returned
/// value from this function is dropped.
pub fn handle_drop(&mut self, info: MapInfo) -> Option<UnmapOnDrop> {
// Missing maps in unmap should be ignored.
let Some(item) = self.maps.get_mut(&info) else {
Expand Down
64 changes: 19 additions & 45 deletions src/runtime/monitor/src/mon/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use std::{collections::HashMap, mem::MaybeUninit, sync::Arc};
use dynlink::tls::TlsRegion;
use twizzler_abi::{
object::NULLPAGE_SIZE,
syscall::{sys_spawn, sys_thread_exit, ThreadSyncSleep, UpcallTargetSpawnOption},
thread::ThreadRepr,
syscall::{
sys_spawn, sys_thread_exit, ThreadSyncReference, ThreadSyncSleep, UpcallTargetSpawnOption,
},
thread::{ExecutionState, ThreadRepr},
upcall::{UpcallFlags, UpcallInfo, UpcallMode, UpcallOptions, UpcallTarget},
};
use twizzler_runtime_api::{ObjID, SpawnError};
Expand All @@ -14,14 +16,17 @@ use crate::{api::MONITOR_INSTANCE_ID, thread::SUPER_UPCALL_STACK_SIZE};

mod cleaner;

/// Manages all threads owned by the monitor. Typically, this is all threads.
/// Threads are spawned here and tracked in the background by a [cleaner::ThreadCleaner]. The thread
/// cleaner detects when a thread has exited and performs any final thread cleanup logic.
pub struct ThreadMgr {
all: HashMap<ObjID, ManagedThread>,
cleaner: cleaner::ThreadCleaner,
}

impl ThreadMgr {
fn do_remove(&mut self, thread: &ManagedThread) {
todo!()
self.all.remove(&thread.id);
}

unsafe fn spawn_thread(
Expand Down Expand Up @@ -57,48 +62,12 @@ impl ThreadMgr {
}

fn do_spawn(start: unsafe extern "C" fn(usize) -> !, arg: usize) -> Result<Self, SpawnError> {
/*
let mut cm = COMPMAN.lock();
let mon_comp = cm.get_monitor_dynlink_compartment();
let super_tls = mon_comp
.build_tls_region(RuntimeThreadControl::default(), |layout| unsafe {
NonNull::new(std::alloc::alloc_zeroed(layout))
})
.map_err(|_| SpawnError::Other)?;
drop(cm);
let super_thread_pointer = super_tls.get_thread_pointer_value();
let super_stack = Box::new_zeroed_slice(SUPER_UPCALL_STACK_SIZE);
// Safety: we are allocating and tracking both the stack and the tls region for greater than
// the lifetime of this thread. The start entry points to our given start function.
let id = unsafe {
Self::spawn_thread(
start as *const () as usize,
super_stack.as_ptr() as usize,
super_thread_pointer,
arg,
)
}?;
// TODO
let repr = crate::mapman::map_object(MapInfo {
id,
flags: MapFlags::READ,
})
.unwrap();
Ok(Self {
id,
super_stack,
super_tls,
repr: ManagedThreadRepr::new(repr),
})
*/
todo!()
}

fn do_start(main: Box<dyn FnOnce()>) -> Result<Self, SpawnError> {
/// Start a thread, running the provided Box'd closure. The thread will be running in
/// monitor-mode, and will have no connection to any compartment.
pub fn start_thread(main: Box<dyn FnOnce()>) -> Result<Self, SpawnError> {
let main_addr = Box::into_raw(Box::new(main)) as usize;
unsafe extern "C" fn managed_thread_entry(main: usize) -> ! {
{
Expand All @@ -113,7 +82,7 @@ impl ThreadMgr {
}
}

#[allow(dead_code)]
/// Internal managed thread data.
pub struct ManagedThreadInner {
pub id: ObjID,
pub(crate) repr: ManagedThreadRepr,
Expand All @@ -122,12 +91,14 @@ pub struct ManagedThreadInner {
}

impl ManagedThreadInner {
/// Check if this thread has exited.
pub fn has_exited(&self) -> bool {
todo!()
self.repr.get_repr().get_state() == ExecutionState::Exited
}

/// Create a ThreadSyncSleep that will wait until the thread has exited.
pub fn waitable_until_exit(&self) -> ThreadSyncSleep {
todo!()
self.repr.get_repr().waitable(ExecutionState::Exited)
}
}

Expand All @@ -147,8 +118,10 @@ impl Drop for ManagedThreadInner {
}
}

/// A thread managed by the monitor.
pub type ManagedThread = Arc<ManagedThreadInner>;

/// An owned handle to a thread's repr object.
pub(crate) struct ManagedThreadRepr {
handle: MapHandle,
}
Expand All @@ -158,6 +131,7 @@ impl ManagedThreadRepr {
Self { handle }
}

/// Get the thread representation structure for the associated thread.
pub fn get_repr(&self) -> &ThreadRepr {
let addr = self.handle.addrs().start + NULLPAGE_SIZE;
unsafe { (addr as *const ThreadRepr).as_ref().unwrap() }
Expand Down

0 comments on commit baa93d2

Please sign in to comment.