1use std::sync::Mutex;
2
3use object_store::ExternalFile;
4use secgate::{
5 secure_gate,
6 util::{Descriptor, SimpleBuffer},
7};
8use twizzler::object::{ObjID, ObjectHandle};
9use twizzler_abi::{
10 object::Protections,
11 syscall::{sys_object_create, BackingType, LifetimeType, ObjectCreate, ObjectCreateFlags},
12};
13use twizzler_rt_abi::{error::TwzError, object::MapFlags};
14
15use crate::{threads::run_async, PAGER_CTX};
16
17pub(crate) struct PagerClient {
19 buffer: SimpleBuffer,
20}
21
22impl PagerClient {
23 fn sbid(&self) -> ObjID {
24 self.buffer.handle().id()
25 }
26
27 pub fn into_handle(self) -> ObjectHandle {
28 self.buffer.into_handle()
29 }
30}
31
32struct SbObjects {
33 objs: Vec<ObjectHandle>,
34}
35
36static SB_OBJECTS: Mutex<SbObjects> = Mutex::new(SbObjects { objs: Vec::new() });
37
38pub fn get_sb_object() -> Result<ObjectHandle, TwzError> {
39 let mut sbo = SB_OBJECTS.lock().unwrap();
40 if sbo.objs.len() == 0 {
41 drop(sbo);
42 let id = sys_object_create(
44 ObjectCreate::new(
45 BackingType::Normal,
46 LifetimeType::Volatile,
47 None,
48 ObjectCreateFlags::empty(),
49 Protections::all(),
50 ),
51 &[],
52 &[],
53 )?;
54 let handle =
55 twizzler_rt_abi::object::twz_rt_map_object(id, MapFlags::WRITE | MapFlags::READ)?;
56 return Ok(handle);
57 }
58
59 let next = sbo.objs.pop().unwrap();
60 Ok(next)
62}
63
64pub fn release_sb_object(obj: ObjectHandle) {
65 let mut sbo = SB_OBJECTS.lock().unwrap();
66 sbo.objs.push(obj);
67}
68
69impl PagerClient {
70 pub fn new() -> Result<Self, TwzError> {
71 let handle = get_sb_object()?;
72 let buffer = SimpleBuffer::new(handle);
73 Ok(Self { buffer })
74 }
75}
76
77#[secure_gate(options(info))]
78pub fn pager_open_handle(info: &secgate::GateCallInfo) -> Result<(Descriptor, ObjID), TwzError> {
79 let comp = info.source_context().unwrap_or(0.into());
80 let pager = &PAGER_CTX.get().unwrap().data;
81 let handle = pager.new_handle(comp)?;
82 let id = pager.with_handle(comp, handle, |pc| pc.sbid())?;
83
84 Ok((handle, id))
85}
86
87#[secure_gate(options(info))]
88pub fn pager_close_handle(info: &secgate::GateCallInfo, desc: Descriptor) -> Result<(), TwzError> {
89 let comp = info.source_context().unwrap_or(0.into());
90 let pager = &PAGER_CTX.get().unwrap().data;
91 if let Some(oh) = pager.drop_handle(comp, desc) {
92 release_sb_object(oh);
93 }
94 Ok(())
95}
96
97#[secure_gate(options(info))]
98pub fn pager_enumerate_external(
99 info: &secgate::GateCallInfo,
100 desc: Descriptor,
101 id: ObjID,
102) -> Result<usize, TwzError> {
103 let comp = info.source_context().unwrap_or(0.into());
104 let pager = &PAGER_CTX.get().unwrap();
105
106 let items = run_async(pager.enumerate_external(id))?;
107
108 pager
109 .data
110 .with_handle_mut(comp, desc, |pc| {
111 let mut len = 0;
112 for (idx, item) in items.iter().enumerate() {
113 let ptr = item as *const ExternalFile;
114 let bytes = unsafe {
115 core::slice::from_raw_parts(ptr.cast::<u8>(), size_of::<ExternalFile>())
116 };
117 len += pc
118 .buffer
119 .write_offset(bytes, idx * size_of::<ExternalFile>());
120 }
121 len
122 })
123 .ok_or(TwzError::INVALID_ARGUMENT)
124}