pager_srv/
handle.rs

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
17// Per-client metadata.
18pub(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        // Create and map a handle for the simple buffer.
43        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    // TODO: discard all object pages.
61    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}