1use std::{collections::BTreeMap, sync::Mutex, time::Instant};
2
3use twizzler_abi::{
4 object::ObjID,
5 syscall::{sys_object_ctrl, ObjectControlCmd},
6};
7use twizzler_rt_abi::{
8 object::{MapFlags, ObjectHandle},
9 Result,
10};
11
12#[derive(Debug, Clone, Copy)]
13#[repr(C)]
14pub struct CachedStats {
15 pub id: ObjID,
16 pub start: Instant,
17 pub flags: MapFlags,
18 pub addr: u64,
19}
20
21type Key = (ObjID, MapFlags);
22
23struct HeldObject {
24 start: Instant,
25 handle: ObjectHandle,
26}
27
28impl HeldObject {
29 fn new(handle: ObjectHandle) -> Self {
30 Self {
31 start: Instant::now(),
32 handle,
33 }
34 }
35}
36
37struct CacheState {
38 map: BTreeMap<Key, HeldObject>,
39}
40
41impl CacheState {
42 const fn new() -> Self {
43 Self {
44 map: BTreeMap::new(),
45 }
46 }
47}
48
49static STATE: Mutex<CacheState> = Mutex::new(CacheState::new());
50
51mod gates {
52 use super::*;
53 #[secgate::entry(lib = "")]
54 pub 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::entry(lib = "")]
64 pub 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::entry(lib = "")]
70 pub fn preload(id: ObjID) -> Result<()> {
71 sys_object_ctrl(id, ObjectControlCmd::Preload)
72 }
73
74 #[secgate::entry(lib = "")]
75 pub fn stat(_id: ObjID) -> Result<()> {
76 Ok(())
77 }
78
79 #[secgate::entry(lib = "")]
80 pub 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 }
93}