1#![feature(naked_functions)]
2
3use std::{collections::BTreeMap, sync::Mutex, time::Instant};
4
5use twizzler_abi::{
6 object::ObjID,
7 syscall::{sys_object_ctrl, ObjectControlCmd},
8};
9use twizzler_rt_abi::{
10 object::{MapFlags, ObjectHandle},
11 Result,
12};
13
14#[derive(Debug, Clone, Copy)]
15#[repr(C)]
16pub struct CachedStats {
17 pub id: ObjID,
18 pub start: Instant,
19 pub flags: MapFlags,
20 pub addr: u64,
21}
22
23type Key = (ObjID, MapFlags);
24
25struct HeldObject {
26 start: Instant,
27 handle: ObjectHandle,
28}
29
30impl HeldObject {
31 fn new(handle: ObjectHandle) -> Self {
32 Self {
33 start: Instant::now(),
34 handle,
35 }
36 }
37}
38
39struct CacheState {
40 map: BTreeMap<Key, HeldObject>,
41}
42
43impl CacheState {
44 const fn new() -> Self {
45 Self {
46 map: BTreeMap::new(),
47 }
48 }
49}
50
51static STATE: Mutex<CacheState> = Mutex::new(CacheState::new());
52
53#[secgate::secure_gate]
54pub fn hold(id: ObjID, flags: MapFlags) -> Result<bool> {
55 let handle = twizzler_rt_abi::object::twz_rt_map_object(id, flags)?;
56 let mut state = STATE.lock().unwrap();
57 Ok(state
58 .map
59 .insert((id, flags), HeldObject::new(handle))
60 .is_some())
61}
62
63#[secgate::secure_gate]
64pub fn drop(id: ObjID, flags: MapFlags) -> Result<bool> {
65 let mut state = STATE.lock().unwrap();
66 Ok(state.map.remove(&(id, flags)).is_some())
67}
68
69#[secgate::secure_gate]
70pub fn preload(id: ObjID) -> Result<()> {
71 sys_object_ctrl(id, ObjectControlCmd::Preload)
72}
73
74#[secgate::secure_gate]
75pub fn stat(_id: ObjID) -> Result<()> {
76 Ok(())
77}
78
79#[secgate::secure_gate]
80pub fn list_nth(nth: u64) -> Result<Option<CachedStats>> {
81 let state = STATE.lock().unwrap();
82 if let Some(v) = state.map.values().nth(nth as usize) {
83 Ok(Some(CachedStats {
84 id: v.handle.id(),
85 flags: v.handle.map_flags(),
86 start: v.start,
87 addr: v.handle.start().addr() as u64,
88 }))
89 } else {
90 Ok(None)
91 }
92}