From aad81a0a87be4cd2f9946df54407a10fc5c0b4b9 Mon Sep 17 00:00:00 2001 From: Daniel Bittman Date: Fri, 21 Feb 2025 13:59:33 -0800 Subject: [PATCH] Fix several recursions in monitor mapping. --- Cargo.lock | 21 ++++-- src/bin/bootstrap/src/main.rs | 28 +++++++- src/lib/dynlink/src/context.rs | 19 +++-- src/lib/dynlink/src/engines/mod.rs | 49 ++++++++----- src/lib/dynlink/src/engines/twizzler.rs | 25 ++----- src/rt/monitor/src/dlengine.rs | 70 +++++++++++++++++-- src/rt/monitor/src/mon/compartment.rs | 53 ++++++++------ .../monitor/src/mon/compartment/compthread.rs | 5 +- src/rt/monitor/src/mon/compartment/loader.rs | 20 +++--- src/rt/monitor/src/mon/compartment/runcomp.rs | 16 +++-- src/rt/monitor/src/mon/library.rs | 12 ++-- src/rt/monitor/src/mon/mod.rs | 36 +++++----- src/rt/monitor/src/mon/space/unmapper.rs | 3 +- src/rt/monitor/src/mon/stat.rs | 3 +- src/rt/monitor/src/mon/thread.rs | 13 ++-- src/rt/monitor/src/mon/thread/cleaner.rs | 19 ++--- src/rt/reference/src/runtime/core.rs | 2 +- src/rt/reference/src/runtime/thread/mgr.rs | 6 +- src/rt/reference/src/runtime/thread/tcb.rs | 10 +-- 19 files changed, 256 insertions(+), 154 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61c5b245..bf2164ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2773,14 +2773,13 @@ dependencies = [ [[package]] name = "happylock" -version = "0.3.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1949ae82dd58a6d8a76ec4761e3b1e01ffd9eb3871cb2d8eba6eda8e66a7b3d6" +checksum = "95a9c5f45d0c6a03e4cfb73cbb249e96b61c63dd64124f9f106fd9bd8d082cb5" dependencies = [ "lock_api", - "once_cell", + "mutants", "parking_lot", - "thread_local", ] [[package]] @@ -3262,6 +3261,7 @@ dependencies = [ "async-io", "futures", "monitor-api", + "naming-core", "polling", "rprompt", "tracing", @@ -3449,6 +3449,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "lazy-init" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f40963626ac12dcaf92afc15e4c3db624858c92fd9f8ba2125eaada3ac2706f" + [[package]] name = "lazy_static" version = "1.5.0" @@ -3916,6 +3922,12 @@ dependencies = [ "twizzler-runtime", ] +[[package]] +name = "mutants" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0287524726960e07b119cebd01678f852f147742ae0d925e6a520dca956126" + [[package]] name = "naming" version = "0.1.0" @@ -3945,6 +3957,7 @@ name = "naming-srv" version = "0.1.0" dependencies = [ "arrayvec", + "lazy-init", "lazy_static", "naming-core", "secgate", diff --git a/src/bin/bootstrap/src/main.rs b/src/bin/bootstrap/src/main.rs index e0e5e208..c6e88a5a 100644 --- a/src/bin/bootstrap/src/main.rs +++ b/src/bin/bootstrap/src/main.rs @@ -10,7 +10,11 @@ use dynlink::{ }; use tracing::{debug, info, warn, Level}; use tracing_subscriber::FmtSubscriber; -use twizzler_abi::{arch::SLOTS, object::ObjID, syscall::sys_object_read_map}; +use twizzler_abi::{ + arch::SLOTS, + object::{ObjID, MAX_SIZE}, + syscall::sys_object_read_map, +}; use twizzler_rt_abi::{ core::{InitInfoPtrs, RuntimeInfo}, object::MapFlags, @@ -36,7 +40,27 @@ impl ContextEngine for Engine { _comp_id: CompartmentId, _load_ctx: &mut LoadCtx, ) -> Result, dynlink::DynlinkError> { - dynlink::engines::twizzler::load_segments(src, ld, 0.into()) + let map = |text_id, data_id| { + #[allow(deprecated)] + let (text_handle, data_handle) = twizzler_rt_abi::object::twz_rt_map_two_objects( + text_id, + MapFlags::READ | MapFlags::EXEC, + data_id, + MapFlags::READ | MapFlags::WRITE, + ) + .map_err(|_| DynlinkErrorKind::NewBackingFail)?; + + if data_handle.start() as usize != text_handle.start() as usize + MAX_SIZE { + tracing::error!( + "internal runtime error: failed to map text and data adjacent and in-order ({:p} {:p})", + text_handle.start(), + data_handle.start() + ); + return Err(DynlinkErrorKind::NewBackingFail.into()); + } + Ok((Backing::new(text_handle), Backing::new(data_handle))) + }; + dynlink::engines::twizzler::load_segments(src, ld, 0.into(), map) } fn load_object(&mut self, unlib: &UnloadedLibrary) -> Result { diff --git a/src/lib/dynlink/src/context.rs b/src/lib/dynlink/src/context.rs index f5865c28..6f24e2ba 100644 --- a/src/lib/dynlink/src/context.rs +++ b/src/lib/dynlink/src/context.rs @@ -211,17 +211,22 @@ impl Context { self.add_dep(parent.0, dependee.0); } - pub fn unload_compartment(&mut self, comp_id: CompartmentId) { + pub fn unload_compartment( + &mut self, + comp_id: CompartmentId, + ) -> (Option, Vec) { let Ok(comp) = self.get_compartment(comp_id) else { - return; + return (None, vec![]); }; let name = comp.name.clone(); - let ids = comp.library_ids().collect::>(); - for lib in ids { - self.library_deps.remove_node(lib.0); - } + let ids = comp.library_ids(); + let nodes = ids + .collect::>() + .iter() + .filter_map(|id| self.library_deps.remove_node(id.0)) + .collect(); self.compartment_names.remove(&name); - self.compartments.remove(comp_id.0); + (self.compartments.remove(comp_id.0), nodes) } /// Create a new compartment with a given name. diff --git a/src/lib/dynlink/src/engines/mod.rs b/src/lib/dynlink/src/engines/mod.rs index ef6dab98..11717814 100644 --- a/src/lib/dynlink/src/engines/mod.rs +++ b/src/lib/dynlink/src/engines/mod.rs @@ -1,11 +1,11 @@ pub mod twizzler; -use std::collections::HashMap; +use std::{any::Any, collections::HashMap, sync::Arc}; use elf::{endian::NativeEndian, ParseError}; use twizzler_abi::object::{MAX_SIZE, NULLPAGE_SIZE}; use twizzler_object::ObjID; -use twizzler_rt_abi::object::{self, ObjectHandle}; +use twizzler_rt_abi::object::ObjectHandle; use crate::{compartment::CompartmentId, library::UnloadedLibrary, DynlinkError}; @@ -56,38 +56,49 @@ bitflags::bitflags! { /// for treating Twizzler objects as object files. #[derive(Clone)] pub struct Backing { - obj: object::ObjectHandle, + _owner: Arc, + start: *mut u8, + len: usize, + id: ObjID, } -impl Drop for Backing { - fn drop(&mut self) { - tracing::debug!("drop backing: {:?}: {:p}", self.obj.id(), self.obj.start()); - } -} +unsafe impl Send for Backing {} +unsafe impl Sync for Backing {} impl Backing { pub fn new(inner: ObjectHandle) -> Self { - tracing::debug!("new backing: {:?}: {:p}", inner.id(), inner.start()); - Self { obj: inner } + unsafe { + Self::new_owned( + inner.start(), + MAX_SIZE - NULLPAGE_SIZE * 2, + inner.id(), + Arc::new(inner), + ) + } + } + + pub unsafe fn new_owned(start: *mut u8, len: usize, id: ObjID, owner: Arc) -> Self { + Self { + _owner: owner, + start, + len, + id, + } } } impl Backing { pub(crate) fn data(&self) -> (*mut u8, usize) { - ( - unsafe { self.obj.start().add(NULLPAGE_SIZE) }, - // one null-page, one meta-page - MAX_SIZE - NULLPAGE_SIZE * 2, - ) + (unsafe { self.start.add(NULLPAGE_SIZE) }, self.len) } /// Get the underlying object handle. - pub fn object(&self) -> &ObjectHandle { - &self.obj + pub fn id(&self) -> ObjID { + self.id } - pub(crate) fn load_addr(&self) -> usize { - self.obj.start() as usize + pub fn load_addr(&self) -> usize { + self.start as usize } pub(crate) fn slice(&self) -> &[u8] { diff --git a/src/lib/dynlink/src/engines/twizzler.rs b/src/lib/dynlink/src/engines/twizzler.rs index abf05403..2cc713c4 100644 --- a/src/lib/dynlink/src/engines/twizzler.rs +++ b/src/lib/dynlink/src/engines/twizzler.rs @@ -7,7 +7,6 @@ use twizzler_abi::{ }, }; use twizzler_object::ObjID; -use twizzler_rt_abi::object::MapFlags; use super::{Backing, LoadDirective, LoadFlags}; use crate::{DynlinkError, DynlinkErrorKind}; @@ -24,6 +23,7 @@ pub fn load_segments( src: &Backing, ld: &[LoadDirective], instance: ObjID, + map: impl FnOnce(ObjID, ObjID) -> Result<(Backing, Backing), DynlinkError>, ) -> Result, DynlinkError> { let create_spec = ObjectCreate::new( BackingType::Normal, @@ -93,7 +93,7 @@ pub fn load_segments( } Ok(ObjectSource::new_copy( - src.obj.id(), + src.id(), src_start as u64, dest_start as u64, len, @@ -133,23 +133,6 @@ pub fn load_segments( data_id ); - #[allow(deprecated)] - let (text_handle, data_handle) = twizzler_rt_abi::object::twz_rt_map_two_objects( - text_id, - MapFlags::READ | MapFlags::EXEC, - data_id, - MapFlags::READ | MapFlags::WRITE, - ) - .map_err(|_| DynlinkErrorKind::NewBackingFail)?; - - if data_handle.start() as usize != text_handle.start() as usize + MAX_SIZE { - tracing::error!( - "internal runtime error: failed to map text and data adjacent and in-order ({:p} {:p})", - text_handle.start(), - data_handle.start() - ); - return Err(DynlinkErrorKind::NewBackingFail.into()); - } - - Ok(vec![Backing::new(text_handle), Backing::new(data_handle)]) + let (text, data) = map(text_id, data_id)?; + Ok(vec![text, data]) } diff --git a/src/rt/monitor/src/dlengine.rs b/src/rt/monitor/src/dlengine.rs index d633e633..61b2c138 100644 --- a/src/rt/monitor/src/dlengine.rs +++ b/src/rt/monitor/src/dlengine.rs @@ -11,6 +11,8 @@ use twizzler_abi::{ }; use twizzler_rt_abi::object::{MapFlags, ObjID}; +use crate::mon::{get_monitor, space::MapInfo}; + pub struct Engine; fn get_new_sctx_instance(_sctx: ObjID) -> ObjID { @@ -40,15 +42,73 @@ impl ContextEngine for Engine { .set .entry(comp_id) .or_insert_with(|| get_new_sctx_instance(1.into())); - dynlink::engines::twizzler::load_segments(src, ld, instance) + let map = |text_id, data_id| { + #[allow(deprecated)] + let (text_handle, data_handle) = get_monitor() + .space + .lock() + .unwrap() + .map_pair( + MapInfo { + id: text_id, + flags: MapFlags::READ | MapFlags::EXEC, + }, + MapInfo { + id: data_id, + flags: MapFlags::READ | MapFlags::WRITE, + }, + ) + .map_err(|_| DynlinkErrorKind::NewBackingFail)?; + + if data_handle.monitor_data_start() as usize + != text_handle.monitor_data_start() as usize + MAX_SIZE + { + tracing::error!( + "internal runtime error: failed to map text and data adjacent and in-order ({:p} {:p})", + text_handle.monitor_data_start(), + data_handle.monitor_data_start(), + ); + return Err(DynlinkErrorKind::NewBackingFail.into()); + } + unsafe { + Ok(( + Backing::new_owned( + text_handle.monitor_data_start(), + MAX_SIZE - NULLPAGE_SIZE * 2, + text_id, + text_handle, + ), + Backing::new_owned( + data_handle.monitor_data_start(), + MAX_SIZE - NULLPAGE_SIZE * 2, + data_id, + data_handle, + ), + )) + } + }; + dynlink::engines::twizzler::load_segments(src, ld, instance, map) } fn load_object(&mut self, unlib: &UnloadedLibrary) -> Result { let id = name_resolver(&unlib.name)?; - Ok(Backing::new( - twizzler_rt_abi::object::twz_rt_map_object(id, MapFlags::READ) - .map_err(|_err| DynlinkErrorKind::NewBackingFail)?, - )) + let mapping = get_monitor() + .space + .lock() + .unwrap() + .map(MapInfo { + id, + flags: MapFlags::READ, + }) + .map_err(|_err| DynlinkErrorKind::NewBackingFail)?; + Ok(unsafe { + Backing::new_owned( + mapping.monitor_data_start(), + MAX_SIZE - NULLPAGE_SIZE * 2, + id, + mapping, + ) + }) } fn select_compartment( diff --git a/src/rt/monitor/src/mon/compartment.rs b/src/rt/monitor/src/mon/compartment.rs index f6870dbf..0508415a 100644 --- a/src/rt/monitor/src/mon/compartment.rs +++ b/src/rt/monitor/src/mon/compartment.rs @@ -1,8 +1,8 @@ use std::{collections::HashMap, ffi::CStr}; use dynlink::{ - compartment::CompartmentId, - context::{Context, NewCompartmentFlags}, + compartment::{Compartment, CompartmentId}, + context::{Context, LoadedOrUnloaded, NewCompartmentFlags}, library::UnloadedLibrary, }; use happylock::ThreadKey; @@ -160,6 +160,7 @@ impl CompartmentMgr { tracing::warn!("failed to find compartment {} during exit", instance); return; }; + tracing::trace!("runcomp usecount: {}", rc.use_count); if rc.use_count == 0 { if let Some(rc) = self.remove(instance) { self.cleanup_queue.push(rc) @@ -187,10 +188,16 @@ impl CompartmentMgr { } } - pub fn process_cleanup_queue(&mut self, dynlink: &mut Context) { - for rc in self.cleanup_queue.drain(..) { - dynlink.unload_compartment(rc.compartment_id); - } + pub fn process_cleanup_queue( + &mut self, + dynlink: &mut Context, + ) -> (Vec>, Vec>) { + let (comps, libs) = self + .cleanup_queue + .drain(..) + .map(|c| dynlink.unload_compartment(c.compartment_id)) + .unzip(); + (comps, libs) } } @@ -204,14 +211,14 @@ impl super::Monitor { thread: ObjID, desc: Option, ) -> Option { - let (ref mut space, _, ref mut comps, ref dynlink, _, ref comphandles) = + let (_, ref mut comps, ref dynlink, _, ref comphandles) = *self.locks.lock(ThreadKey::get().unwrap()); let comp_id = desc .map(|comp| comphandles.lookup(instance, comp).map(|ch| ch.instance)) .unwrap_or(Some(instance))?; let name = comps.get(comp_id)?.name.clone(); - let pt = comps.get_mut(instance)?.get_per_thread(thread, space); + let pt = comps.get_mut(instance)?.get_per_thread(thread); let name_len = pt.write_bytes(name.as_bytes()); let comp = comps.get(comp_id)?; let nr_libs = dynlink @@ -240,7 +247,7 @@ impl super::Monitor { name_len: usize, ) -> Option { let name = self.read_thread_simple_buffer(instance, thread, name_len)?; - let (_, _, ref comps, ref dynlink, _, ref comphandles) = + let (_, ref comps, ref dynlink, _, ref comphandles) = *self.locks.lock(ThreadKey::get().unwrap()); let comp_id = desc .map(|comp| comphandles.lookup(instance, comp).map(|ch| ch.instance)) @@ -265,7 +272,7 @@ impl super::Monitor { /// Open a compartment handle for this caller compartment. #[tracing::instrument(skip(self), level = tracing::Level::DEBUG)] pub fn get_compartment_handle(&self, caller: ObjID, compartment: ObjID) -> Option { - let (_, _, ref mut comps, _, _, ref mut ch) = *self.locks.lock(ThreadKey::get().unwrap()); + let (_, ref mut comps, _, _, ref mut ch) = *self.locks.lock(ThreadKey::get().unwrap()); let comp = comps.get_mut(compartment)?; comp.inc_use_count(); ch.insert( @@ -290,7 +297,7 @@ impl super::Monitor { ) -> Option { let name = self.read_thread_simple_buffer(instance, thread, name_len)?; let name = String::from_utf8(name).ok()?; - let (_, _, ref mut comps, _, _, ref mut ch) = *self.locks.lock(ThreadKey::get().unwrap()); + let (_, ref mut comps, _, _, ref mut ch) = *self.locks.lock(ThreadKey::get().unwrap()); let comp = comps.get_name_mut(&name)?; comp.inc_use_count(); ch.insert( @@ -325,7 +332,7 @@ impl super::Monitor { dep_n: usize, ) -> Option { let dep = { - let (_, _, ref mut comps, _, _, ref mut comphandles) = + let (_, ref mut comps, _, _, ref mut comphandles) = *self.locks.lock(ThreadKey::get().unwrap()); let comp_id = desc .map(|comp| comphandles.lookup(caller, comp).map(|ch| ch.instance)) @@ -385,10 +392,10 @@ impl super::Monitor { .map_err(|_| LoadCompartmentError::Unknown)?; let root_comp = { - let (ref mut space, _, ref mut cmp, ref mut dynlink, _, _) = + let (_, ref mut cmp, ref mut dynlink, _, _) = &mut *self.locks.lock(ThreadKey::get().unwrap()); loader - .build_rcs(&mut *cmp, &mut *dynlink, &mut *space) + .build_rcs(&mut *cmp, &mut *dynlink) .inspect_err(|e| { tracing::debug!( "failed to build runtime compartments {}::{}: {}", @@ -412,14 +419,18 @@ impl super::Monitor { /// Drop a compartment handle. #[tracing::instrument(skip(self), level = tracing::Level::DEBUG)] pub fn drop_compartment_handle(&self, caller: ObjID, desc: Descriptor) { - let (_, _, ref mut cmgr, ref mut dynlink, _, ref mut comp_handles) = - *self.locks.lock(ThreadKey::get().unwrap()); - let comp = comp_handles.remove(caller, desc); + let comps = { + let (_, ref mut cmgr, ref mut dynlink, _, ref mut comp_handles) = + *self.locks.lock(ThreadKey::get().unwrap()); + let comp = comp_handles.remove(caller, desc); - if let Some(comp) = comp { - cmgr.dec_use_count(comp.instance); - } - cmgr.process_cleanup_queue(&mut *dynlink); + if let Some(comp) = comp { + cmgr.dec_use_count(comp.instance); + } + cmgr.process_cleanup_queue(&mut *dynlink) + }; + tracing::trace!("HRE"); + drop(comps); } #[tracing::instrument(skip(self, f), level = tracing::Level::DEBUG)] diff --git a/src/rt/monitor/src/mon/compartment/compthread.rs b/src/rt/monitor/src/mon/compartment/compthread.rs index 33bbf7ab..8a087255 100644 --- a/src/rt/monitor/src/mon/compartment/compthread.rs +++ b/src/rt/monitor/src/mon/compartment/compthread.rs @@ -4,7 +4,7 @@ use twizzler_abi::{object::MAX_SIZE, upcall::UpcallFrame}; use twizzler_rt_abi::object::ObjID; use crate::mon::{ - space::{MapHandle, Space}, + space::MapHandle, thread::{ManagedThread, ThreadMgr, DEFAULT_STACK_SIZE, STACK_SIZE_MIN_ALIGN}, }; @@ -19,7 +19,6 @@ impl CompThread { /// the start function. #[allow(clippy::too_many_arguments)] pub fn new( - space: &mut Space, tmgr: &mut ThreadMgr, dynlink: &mut Context, stack: StackObject, @@ -35,7 +34,7 @@ impl CompThread { }; let mon = dynlink.get_compartment_mut(MONITOR_COMPARTMENT_ID).unwrap(); let mt = tmgr - .start_thread(space, mon, Box::new(start), main_thread_comp) + .start_thread(mon, Box::new(start), main_thread_comp) .into_diagnostic()?; Ok(Self { stack_object: stack, diff --git a/src/rt/monitor/src/mon/compartment/loader.rs b/src/rt/monitor/src/mon/compartment/loader.rs index dee8af8e..dec9a978 100644 --- a/src/rt/monitor/src/mon/compartment/loader.rs +++ b/src/rt/monitor/src/mon/compartment/loader.rs @@ -20,11 +20,7 @@ use super::{ }; use crate::{ gates::LoadCompartmentError, - mon::{ - space::{MapHandle, Space}, - thread::DEFAULT_STACK_SIZE, - Monitor, - }, + mon::{get_monitor, space::MapHandle, thread::DEFAULT_STACK_SIZE, Monitor}, }; /// Tracks info for loaded, but not yet running, compartments. @@ -221,10 +217,14 @@ impl RunCompLoader { self, cmp: &mut CompartmentMgr, dynlink: &mut Context, - space: &mut Space, ) -> miette::Result { - let mut make_new_handle = - |id| space.safe_create_and_map_runtime_object(id, MapFlags::READ | MapFlags::WRITE); + let make_new_handle = |id| { + get_monitor() + .space + .lock() + .unwrap() + .safe_create_and_map_runtime_object(id, MapFlags::READ | MapFlags::WRITE) + }; let root_rc = self.root_comp.build_runcomp( make_new_handle(self.root_comp.sctx_id)?, @@ -336,11 +336,11 @@ impl Monitor { return Ok(()); } let info = { - let (ref mut space, ref mut tmgr, ref mut cmp, ref mut dynlink, _, _) = + let (ref mut tmgr, ref mut cmp, ref mut dynlink, _, _) = *self.locks.lock(ThreadKey::get().unwrap()); let rc = cmp.get_mut(instance).ok_or(LoadCompartmentError::Unknown)?; - rc.start_main_thread(state, &mut *space, &mut *tmgr, &mut *dynlink, args, env) + rc.start_main_thread(state, &mut *tmgr, &mut *dynlink, args, env) }; if info.is_none() { return Err(LoadCompartmentError::Unknown); diff --git a/src/rt/monitor/src/mon/compartment/runcomp.rs b/src/rt/monitor/src/mon/compartment/runcomp.rs index 30590353..b1488905 100644 --- a/src/rt/monitor/src/mon/compartment/runcomp.rs +++ b/src/rt/monitor/src/mon/compartment/runcomp.rs @@ -21,7 +21,8 @@ use twizzler_rt_abi::{ use super::{compconfig::CompConfigObject, compthread::CompThread, StackObject}; use crate::mon::{ - space::{MapHandle, MapInfo, Space}, + get_monitor, + space::{MapHandle, MapInfo}, thread::ThreadMgr, }; @@ -93,8 +94,11 @@ impl PerThread { /// handled gracefully. This means that if the thread fails to allocate a simple buffer, it /// will just forego having one. This may cause a failure down the line, but it's the best we /// can do without panicing. - fn new(instance: ObjID, _th: ObjID, space: &mut Space) -> Self { - let handle = space + fn new(instance: ObjID, _th: ObjID) -> Self { + let handle = get_monitor() + .space + .lock() + .unwrap() .safe_create_and_map_runtime_object(instance, MapFlags::READ | MapFlags::WRITE) .ok(); @@ -165,10 +169,10 @@ impl RunComp { } /// Get per-thread data in this compartment. - pub fn get_per_thread(&mut self, id: ObjID, space: &mut Space) -> &mut PerThread { + pub fn get_per_thread(&mut self, id: ObjID) -> &mut PerThread { self.per_thread .entry(id) - .or_insert_with(|| PerThread::new(self.instance, id, space)) + .or_insert_with(|| PerThread::new(self.instance, id)) } /// Remove all per-thread data for a given thread. @@ -271,7 +275,6 @@ impl RunComp { pub(crate) fn start_main_thread( &mut self, state: u64, - space: &mut Space, tmgr: &mut ThreadMgr, dynlink: &mut Context, args: &[&CStr], @@ -358,7 +361,6 @@ impl RunComp { } let mt = match CompThread::new( - space, tmgr, dynlink, stack, diff --git a/src/rt/monitor/src/mon/library.rs b/src/rt/monitor/src/mon/library.rs index aa675216..6c16527d 100644 --- a/src/rt/monitor/src/mon/library.rs +++ b/src/rt/monitor/src/mon/library.rs @@ -22,19 +22,19 @@ impl Monitor { thread: ObjID, desc: Descriptor, ) -> Option { - let (ref mut space, _, ref mut comps, ref dynlink, ref libhandles, _) = + let (_, ref mut comps, ref dynlink, ref libhandles, _) = *self.locks.lock(ThreadKey::get().unwrap()); let handle = libhandles.lookup(instance, desc)?; let lib = dynlink.get_library(handle.id).ok()?; // write the library name to the per-thread simple buffer - let pt = comps.get_mut(instance)?.get_per_thread(thread, space); + let pt = comps.get_mut(instance)?.get_per_thread(thread); let name_len = pt.write_bytes(lib.name.as_bytes()); Some(LibraryInfo { name_len, compartment_id: handle.comp, - objid: lib.full_obj.object().id(), - slot: lib.full_obj.object().start() as usize / MAX_SIZE, - start: (lib.full_obj.object().start() as usize + NULLPAGE_SIZE) as *mut _, + objid: lib.full_obj.id(), + slot: lib.full_obj.load_addr() / MAX_SIZE, + start: (lib.full_obj.load_addr() + NULLPAGE_SIZE) as *mut _, len: MAX_SIZE - NULLPAGE_SIZE * 2, dl_info: twizzler_rt_abi::debug::DlPhdrInfo { addr: lib.base_addr(), @@ -57,7 +57,7 @@ impl Monitor { comp: Option, num: usize, ) -> Option { - let (_, _, ref mut comps, ref dynlink, ref mut handles, ref comphandles) = + let (_, ref mut comps, ref dynlink, ref mut handles, ref comphandles) = *self.locks.lock(ThreadKey::get().unwrap()); let comp_id = comp .map(|comp| comphandles.lookup(caller, comp).map(|ch| ch.instance)) diff --git a/src/rt/monitor/src/mon/mod.rs b/src/rt/monitor/src/mon/mod.rs index 3b94fd2a..68c8c206 100644 --- a/src/rt/monitor/src/mon/mod.rs +++ b/src/rt/monitor/src/mon/mod.rs @@ -1,4 +1,7 @@ -use std::{ptr::NonNull, sync::OnceLock}; +use std::{ + ptr::NonNull, + sync::{Mutex, OnceLock}, +}; use compartment::{ StackObject, COMP_DESTRUCTED, COMP_EXITED, COMP_IS_BINARY, COMP_READY, COMP_STARTED, @@ -39,7 +42,7 @@ pub struct Monitor { locks: LockCollection>, unmapper: OnceLock, /// Management of address space. - pub space: &'static RwLock, + pub space: &'static Mutex, /// Management of all threads. pub thread_mgr: &'static RwLock, /// Management of compartments. @@ -55,7 +58,6 @@ pub struct Monitor { // We allow locking individually, using eg mon.space.write(key), or locking the collection for more // complex operations that touch multiple pieces of state. type MonitorLocks<'a> = ( - &'a RwLock, &'a RwLock, &'a RwLock, &'a RwLock<&'static mut dynlink::context::Context>, @@ -121,7 +123,7 @@ impl Monitor { // Allocate and leak all the locks (they are global and eternal, so we can do this to safely // and correctly get &'static lifetime) - let space = Box::leak(Box::new(RwLock::new(space))); + let space = Box::leak(Box::new(Mutex::new(space))); let thread_mgr = Box::leak(Box::new(RwLock::new(thread::ThreadMgr::default()))); let comp_mgr = Box::leak(Box::new(RwLock::new(comp_mgr))); let dynlink = Box::leak(Box::new(RwLock::new(ctx))); @@ -131,7 +133,6 @@ impl Monitor { // Okay to call try_new here, since it's not many locks and only happens once. Self { locks: LockCollection::try_new(( - &*space, &*thread_mgr, &*comp_mgr, &*dynlink, @@ -155,10 +156,8 @@ impl Monitor { let key = ThreadKey::get().unwrap(); let locks = &mut *self.locks.lock(key); - let monitor_dynlink_comp = locks.3.get_compartment_mut(MONITOR_COMPARTMENT_ID).unwrap(); - locks - .1 - .start_thread(&mut locks.0, monitor_dynlink_comp, main, None) + let monitor_dynlink_comp = locks.2.get_compartment_mut(MONITOR_COMPARTMENT_ID).unwrap(); + locks.0.start_thread(monitor_dynlink_comp, main, None) } /// Spawn a thread into a given compartment, using initial thread arguments. @@ -194,7 +193,7 @@ impl Monitor { /// Map an object into a given compartment. #[tracing::instrument(skip(self), level = tracing::Level::DEBUG)] pub fn map_object(&self, sctx: ObjID, info: MapInfo) -> Result { - let handle = self.space.write(ThreadKey::get().unwrap()).map(info)?; + let handle = self.space.lock().unwrap().map(info)?; let mut comp_mgr = self.comp_mgr.write(ThreadKey::get().unwrap()); let rc = comp_mgr.get_mut(sctx).ok_or(MapError::InvalidArgument)?; @@ -210,10 +209,7 @@ impl Monitor { info: MapInfo, info2: MapInfo, ) -> Result<(MapHandle, MapHandle), MapError> { - let (handle, handle2) = self - .space - .write(ThreadKey::get().unwrap()) - .map_pair(info, info2)?; + let (handle, handle2) = self.space.lock().unwrap().map_pair(info, info2)?; let mut comp_mgr = self.comp_mgr.write(ThreadKey::get().unwrap()); let rc = comp_mgr.get_mut(sctx).ok_or(MapError::InvalidArgument)?; @@ -242,9 +238,9 @@ impl Monitor { #[tracing::instrument(skip(self), level = tracing::Level::DEBUG)] pub fn get_thread_simple_buffer(&self, sctx: ObjID, thread: ObjID) -> Option { let mut locks = self.locks.lock(ThreadKey::get().unwrap()); - let (ref mut space, _, ref mut comps, _, _, _) = *locks; + let (_, ref mut comps, _, _, _) = *locks; let rc = comps.get_mut(sctx)?; - let pt = rc.get_per_thread(thread, &mut *space); + let pt = rc.get_per_thread(thread); pt.simple_buffer_id() } @@ -257,9 +253,9 @@ impl Monitor { bytes: &[u8], ) -> Option { let mut locks = self.locks.lock(ThreadKey::get().unwrap()); - let (ref mut space, _, ref mut comps, _, _, _) = *locks; + let (_, ref mut comps, _, _, _) = *locks; let rc = comps.get_mut(sctx)?; - let pt = rc.get_per_thread(thread, &mut *space); + let pt = rc.get_per_thread(thread); Some(pt.write_bytes(bytes)) } @@ -272,9 +268,9 @@ impl Monitor { len: usize, ) -> Option> { let mut locks = self.locks.lock(ThreadKey::get().unwrap()); - let (ref mut space, _, ref mut comps, _, _, _) = *locks; + let (_, ref mut comps, _, _, _) = *locks; let rc = comps.get_mut(sctx)?; - let pt = rc.get_per_thread(thread, &mut *space); + let pt = rc.get_per_thread(thread); Some(pt.read_bytes(len)) } diff --git a/src/rt/monitor/src/mon/space/unmapper.rs b/src/rt/monitor/src/mon/space/unmapper.rs index 137561ae..22dec15c 100644 --- a/src/rt/monitor/src/mon/space/unmapper.rs +++ b/src/rt/monitor/src/mon/space/unmapper.rs @@ -22,7 +22,6 @@ impl Unmapper { _thread: std::thread::Builder::new() .name("unmapper".to_string()) .spawn(move || loop { - let key = happylock::ThreadKey::get().unwrap(); match receiver.recv() { Ok(info) => { tracing::debug!("unmapper command {:?}", info); @@ -30,7 +29,7 @@ impl Unmapper { let monitor = get_monitor(); match info { UnmapCommand::SpaceUnmap(info) => { - let mut space = monitor.space.write(key); + let mut space = monitor.space.lock().unwrap(); space.handle_drop(info); } } diff --git a/src/rt/monitor/src/mon/stat.rs b/src/rt/monitor/src/mon/stat.rs index facca4ec..1c74d348 100644 --- a/src/rt/monitor/src/mon/stat.rs +++ b/src/rt/monitor/src/mon/stat.rs @@ -9,7 +9,6 @@ impl Monitor { #[tracing::instrument(skip(self), level = tracing::Level::DEBUG)] pub fn stats(&self) -> MonitorStats { let ( - ref mut space, ref mut threads, ref mut comp, ref mut dynlink, @@ -31,7 +30,7 @@ impl Monitor { nr_lib_handles: lib_handles.total_count(), }; MonitorStats { - space: space.stat(), + space: self.space.lock().unwrap().stat(), thread_mgr: threads.stat(), comp_mgr: comp.stat(), handles, diff --git a/src/rt/monitor/src/mon/thread.rs b/src/rt/monitor/src/mon/thread.rs index 1c818c51..aa23dfdf 100644 --- a/src/rt/monitor/src/mon/thread.rs +++ b/src/rt/monitor/src/mon/thread.rs @@ -18,7 +18,10 @@ use twizzler_rt_abi::{ thread::SpawnError, }; -use super::space::{MapHandle, MapInfo, Space}; +use super::{ + get_monitor, + space::{MapHandle, MapInfo}, +}; use crate::gates::ThreadMgrStats; mod cleaner; @@ -137,7 +140,6 @@ impl ThreadMgr { fn do_spawn( &mut self, - space: &mut Space, monitor_dynlink_comp: &mut Compartment, start: unsafe extern "C" fn(usize) -> !, arg: usize, @@ -163,7 +165,10 @@ impl ThreadMgr { arg, )? }; - let repr = space + let repr = get_monitor() + .space + .lock() + .unwrap() .map(MapInfo { id, flags: MapFlags::READ, @@ -183,7 +188,6 @@ impl ThreadMgr { /// monitor-mode, and will have no connection to any compartment. pub fn start_thread( &mut self, - space: &mut Space, monitor_dynlink_comp: &mut Compartment, main: Box, main_thread_comp: Option, @@ -199,7 +203,6 @@ impl ThreadMgr { } let mt = self.do_spawn( - space, monitor_dynlink_comp, managed_thread_entry, main_addr, diff --git a/src/rt/monitor/src/mon/thread/cleaner.rs b/src/rt/monitor/src/mon/thread/cleaner.rs index 8b3f5fca..0d054ee1 100644 --- a/src/rt/monitor/src/mon/thread/cleaner.rs +++ b/src/rt/monitor/src/mon/thread/cleaner.rs @@ -138,14 +138,17 @@ fn cleaner_thread_main(data: Pin>, mut recv: Receiver = RwLock::new(TlsGenMgr { +pub(crate) static TLS_GEN_MGR: Mutex = Mutex::new(TlsGenMgr { map: BTreeMap::new(), });