Skip to content

Commit

Permalink
Implements basic persistence for twizzler::vec (#256)
Browse files Browse the repository at this point in the history
* Working on persisting.

* Split memory in the kernel for the pager.

* Testing.

* Add mapping options.

* Working on persisting.

* Working on unmapping.

* Add ties.

* Tie dl objects to instance.

* Got unmapping working.

* Got unmapping working.

* Searching for deadlock.

* Fix deadlocks.

* Cleanup.
  • Loading branch information
dbittman authored Jan 31, 2025
1 parent b12a4d5 commit 6ae1f18
Show file tree
Hide file tree
Showing 51 changed files with 866 additions and 216 deletions.
13 changes: 12 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/abi
16 changes: 12 additions & 4 deletions src/bin/bootstrap/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::process::exit;

use dynlink::{
compartment::MONITOR_COMPARTMENT_ID,
compartment::{CompartmentId, MONITOR_COMPARTMENT_ID},
context::{runtime::RuntimeInitInfo, NewCompartmentFlags},
engines::{Backing, ContextEngine},
engines::{Backing, ContextEngine, LoadCtx},
library::{AllowedGates, UnloadedLibrary},
symbol::LookupFlags,
DynlinkError, DynlinkErrorKind,
Expand Down Expand Up @@ -33,8 +33,10 @@ impl ContextEngine for Engine {
&mut self,
src: &Backing,
ld: &[dynlink::engines::LoadDirective],
_comp_id: CompartmentId,
_load_ctx: &mut LoadCtx,
) -> Result<Vec<Backing>, dynlink::DynlinkError> {
dynlink::engines::twizzler::load_segments(src, ld)
dynlink::engines::twizzler::load_segments(src, ld, 0.into())
}

fn load_object(&mut self, unlib: &UnloadedLibrary) -> Result<Backing, DynlinkError> {
Expand Down Expand Up @@ -74,7 +76,12 @@ fn start_runtime(_runtime_monitor: ObjID, _runtime_library: ObjID) -> ! {
.unwrap();

let monitor_id = ctx
.load_library_in_compartment(monitor_comp_id, unlib, AllowedGates::PublicInclSelf)
.load_library_in_compartment(
monitor_comp_id,
unlib,
AllowedGates::PublicInclSelf,
&mut LoadCtx::default(),
)
.unwrap()[0]
.lib;

Expand Down Expand Up @@ -121,6 +128,7 @@ fn start_runtime(_runtime_monitor: ObjID, _runtime_library: ObjID) -> ! {
}
info.used_slots = used;

std::mem::forget(ctx);
debug!("jumping to {:x}", value);
(ptr)(rtinfo_ptr as usize);

Expand Down
1 change: 1 addition & 0 deletions src/bin/init/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ polling = "3.6.0"
futures = "*"
twizzler-futures = { path = "../../lib/twizzler-futures" }
monitor-api = { path = "../../rt/monitor-api" }
twizzler = { path = "../../lib/twizzler" }
2 changes: 2 additions & 0 deletions src/bin/init/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ fn main() {
println!("If you wanted line-editing, you've come to the wrong place.");
println!("To run a program, type its name.");
loop {
//let mstats = monitor_api::stats().unwrap();
//println!("{:?}", mstats);
let reply = rprompt::prompt_reply_stdout("> ").unwrap();
let cmd: Vec<&str> = reply.split_whitespace().collect();
if cmd.len() == 0 {
Expand Down
16 changes: 15 additions & 1 deletion src/kernel/src/memory/context/virtmem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ impl VirtContext {
.expect("cannot get arch mapper for unattached security context"))
}

pub fn print_objects(&self) {
let slots = self.slots.lock();
for obj in &slots.objs {
logln!("{} => {:?}", obj.0, obj.1);
}
}

pub fn register_sctx(&self, sctx: ObjID, arch: ArchContext) {
let mut secctx = self.secctx.lock();
if secctx.contains_key(&sctx) {
Expand Down Expand Up @@ -715,7 +722,14 @@ pub fn page_fault(addr: VirtAddr, cause: MemoryAccessKind, flags: PageFaultFlags
));

if info.obj.use_pager() {
crate::pager::get_object_page(&info.obj, page_number);
let mut obj_page_tree = info.obj.lock_page_tree();
if matches!(
obj_page_tree.get_page(page_number, false),
PageStatus::NoPage
) {
drop(obj_page_tree);
crate::pager::get_object_page(&info.obj, page_number);
}
}

let mut obj_page_tree = info.obj.lock_page_tree();
Expand Down
3 changes: 1 addition & 2 deletions src/kernel/src/memory/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
use alloc::vec::Vec;
use core::{
intrinsics::size_of,
mem::transmute,
mem::{size_of, transmute},
sync::atomic::{AtomicU8, Ordering},
};

Expand Down
15 changes: 15 additions & 0 deletions src/kernel/src/memory/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod frame;
pub mod pagetables;

pub use arch::{PhysAddr, VirtAddr};
use twizzler_abi::object::NULLPAGE_SIZE;

use self::context::{KernelMemoryContext, UserContext};

Expand All @@ -25,6 +26,20 @@ pub struct MemoryRegion {
pub kind: MemoryRegionKind,
}

impl MemoryRegion {
pub fn split(mut self, len: usize) -> Option<(MemoryRegion, MemoryRegion)> {
let len = len.next_multiple_of(NULLPAGE_SIZE);
if self.length <= len {
return None;
}
let mut second = self;
second.start = self.start.offset(len).ok()?;
second.length -= len;
self.length = len;
Some((self, second))
}
}

pub fn init<B: BootInfo>(boot_info: &B) {
frame::init(boot_info.memory_regions());
let kc = context::kernel_context();
Expand Down
55 changes: 44 additions & 11 deletions src/kernel/src/obj/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use range::PageStatus;
use twizzler_abi::{
meta::MetaFlags,
object::{ObjID, MAX_SIZE},
syscall::LifetimeType,
syscall::{CreateTieSpec, LifetimeType},
};

use self::{pages::Page, thread_sync::SleepInfo};
Expand All @@ -32,6 +32,7 @@ pub mod pages;
pub mod pagevec;
pub mod range;
pub mod thread_sync;
pub mod ties;

const OBJ_DELETED: u32 = 1;
pub struct Object {
Expand All @@ -42,6 +43,7 @@ pub struct Object {
pin_info: Mutex<PinInfo>,
contexts: Mutex<ContextInfo>,
lifetime_type: LifetimeType,
ties: Vec<CreateTieSpec>,
}

#[derive(Default)]
Expand Down Expand Up @@ -234,14 +236,15 @@ impl Object {
Some((v, token))
}

pub fn new(id: ObjID, lifetime_type: LifetimeType) -> Self {
pub fn new(id: ObjID, lifetime_type: LifetimeType, ties: &[CreateTieSpec]) -> Self {
Self {
id,
flags: AtomicU32::new(0),
range_tree: Mutex::new(range::PageRangeTree::new()),
sleep_info: Mutex::new(SleepInfo::new()),
pin_info: Mutex::new(PinInfo::default()),
contexts: Mutex::new(ContextInfo::default()),
ties: ties.to_vec(),
lifetime_type,
}
}
Expand All @@ -250,6 +253,7 @@ impl Object {
Self::new(
calculate_new_id(0.into(), MetaFlags::default()),
LifetimeType::Volatile,
&[],
)
}

Expand Down Expand Up @@ -277,6 +281,12 @@ impl Object {
}
}

impl Drop for Object {
fn drop(&mut self) {
//logln!("Dropping object {}", self.id);
}
}

#[derive(Clone, Copy, Debug)]
pub enum InvalidateMode {
Full,
Expand Down Expand Up @@ -329,6 +339,7 @@ struct ObjectManager {
}

bitflags::bitflags! {
#[derive(Debug)]
pub struct LookupFlags: u32 {
const ALLOW_DELETED = 1;
}
Expand Down Expand Up @@ -368,20 +379,21 @@ impl ObjectManager {
}
}

fn lookup_object(&self, id: ObjID, flags: LookupFlags) -> LookupResult {
fn lookup_object(&self, id: ObjID, _flags: LookupFlags) -> LookupResult {
if self.no_exist.lock().contains(&id) {
return LookupResult::WasDeleted;
}
self.map
if let Some(res) = self
.map
.lock()
.get(&id)
.map_or(LookupResult::NotFound, |obj| {
if !obj.is_pending_delete() || flags.contains(LookupFlags::ALLOW_DELETED) {
LookupResult::Found(obj.clone())
} else {
LookupResult::WasDeleted
}
})
.map(|obj| LookupResult::Found(obj.clone()))
{
return res;
}
ties::TIE_MGR
.lookup_object(id)
.map_or(LookupResult::NotFound, |obj| LookupResult::Found(obj))
}

fn register_object(&self, obj: Arc<Object>) {
Expand All @@ -390,6 +402,26 @@ impl ObjectManager {
}
}

pub fn scan_deleted() {
let dobjs = {
let mut om = OBJ_MANAGER.map.lock();
om.extract_if(|_, obj| {
if obj.is_pending_delete() {
let ctx = obj.contexts.lock();
let pin = obj.pin_info.lock();

ctx.contexts.len() == 0 && pin.pins.len() == 0
} else {
false
}
})
.collect::<Vec<_>>()
};
for dobj in dobjs {
ties::TIE_MGR.delete_object(dobj.1);
}
}

lazy_static::lazy_static! {
static ref OBJ_MANAGER: ObjectManager = ObjectManager::new();
}
Expand All @@ -401,6 +433,7 @@ pub fn lookup_object(id: ObjID, flags: LookupFlags) -> LookupResult {

pub fn register_object(obj: Arc<Object>) {
let om = &OBJ_MANAGER;
ties::TIE_MGR.create_object_ties(obj.id(), obj.ties.iter().map(|tie| tie.id));
om.register_object(obj);
}

Expand Down
4 changes: 2 additions & 2 deletions src/kernel/src/obj/pages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ impl Drop for Page {
FrameOrWired::Frame(f) => {
free_frame(f);
}
// Note: this could be a wired, but freeable page (see kernel quick control objects).
FrameOrWired::Wired(_) => todo!(),
// TODO: this could be a wired, but freeable page (see kernel quick control objects).
FrameOrWired::Wired(_) => {}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/kernel/src/obj/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ pub struct PageRangeTree {
tree: NonOverlappingIntervalTree<PageNumber, PageRange>,
}

#[derive(Debug)]
pub enum PageStatus {
Ready(PageRef, bool),
NoPage,
Expand Down
15 changes: 14 additions & 1 deletion src/kernel/src/obj/thread_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,25 @@ use alloc::collections::BTreeMap;
use twizzler_abi::syscall::{ThreadSyncFlags, ThreadSyncOp};

use super::Object;
use crate::thread::{current_thread_ref, ThreadRef};
use crate::{
syscall::sync::add_to_requeue,
thread::{current_thread_ref, ThreadRef},
};

struct SleepEntry {
threads: BTreeMap<u64, ThreadRef>,
}

impl Drop for SleepEntry {
fn drop(&mut self) {
while let Some(t) = self.threads.pop_first() {
if t.1.reset_sync_sleep() {
add_to_requeue(t.1);
}
}
}
}

pub struct SleepInfo {
words: BTreeMap<usize, SleepEntry>,
}
Expand Down
Loading

0 comments on commit 6ae1f18

Please sign in to comment.