twizzler/ptr/
invariant.rs

1use std::marker::PhantomData;
2
3use twizzler_rt_abi::{
4    error::TwzError,
5    object::{MapFlags, ObjectHandle, MAX_SIZE},
6};
7
8use super::{GlobalPtr, Ref, RefMut};
9use crate::{
10    marker::{Invariant, PhantomStoreEffect},
11    object::{FotEntry, RawObject},
12};
13
14#[repr(C)]
15#[derive(Debug, PartialEq, PartialOrd, Ord, Eq)]
16pub struct InvPtr<T: Invariant> {
17    value: u64,
18    _pse: PhantomStoreEffect,
19    _pd: PhantomData<*const T>,
20}
21
22unsafe impl<T: Invariant> Invariant for InvPtr<T> {}
23
24impl<T: Invariant> InvPtr<T> {
25    fn get_this(this: *const Self) -> ObjectHandle {
26        twizzler_rt_abi::object::twz_rt_get_object_handle(this.cast()).unwrap()
27    }
28
29    pub fn global(&self) -> GlobalPtr<T> {
30        let fote = self.fot_index();
31        let obj = Self::get_this(self);
32        if fote == 0 {
33            return GlobalPtr::new(obj.id(), self.offset());
34        }
35        let re = twizzler_rt_abi::object::twz_rt_resolve_fot(&obj, fote, MAX_SIZE, MapFlags::READ)
36            .unwrap();
37        GlobalPtr::new(re.id(), self.offset())
38    }
39
40    #[inline(always)]
41    fn local_resolve(&self) -> *mut T {
42        let this = self as *const Self as *mut Self;
43        this.map_addr(|addr| (addr & !(MAX_SIZE - 1)) + self.offset() as usize)
44            .cast()
45    }
46
47    #[inline]
48    pub unsafe fn resolve(&self) -> Ref<'_, T> {
49        if core::intrinsics::likely(self.is_local()) {
50            return Ref::from_ptr(self.local_resolve());
51        }
52        let res = self
53            .slow_resolve(MapFlags::READ | MapFlags::INDIRECT)
54            .expect("failed to resolve ptr");
55        if let Some(re) = res.1 {
56            Ref::from_handle(re, res.0)
57        } else {
58            Ref::from_ptr(res.0)
59        }
60    }
61
62    #[inline]
63    pub unsafe fn resolve_mut(&self) -> RefMut<'_, T> {
64        if core::intrinsics::likely(self.is_local()) {
65            return RefMut::from_ptr(self.local_resolve());
66        }
67        let res = self
68            .slow_resolve(MapFlags::WRITE | MapFlags::READ | MapFlags::PERSIST)
69            .expect("failed to resolve ptr");
70        if let Some(re) = res.1 {
71            RefMut::from_handle(re, res.0)
72        } else {
73            RefMut::from_ptr(res.0)
74        }
75    }
76
77    #[inline(never)]
78    unsafe fn slow_resolve(
79        &self,
80        flags: MapFlags,
81    ) -> Result<(*mut T, Option<ObjectHandle>), TwzError> {
82        let fote = self.fot_index();
83        let res: *mut u8 = twizzler_rt_abi::object::twz_rt_resolve_fot_local(
84            self as *const Self as *mut u8,
85            fote,
86            MAX_SIZE,
87            flags,
88        );
89        if !res.is_null() {
90            return Ok((res.add(self.offset() as usize).cast(), None));
91        }
92
93        let obj = Self::get_this(self);
94        let re = twizzler_rt_abi::object::twz_rt_resolve_fot(&obj, fote, MAX_SIZE, flags).unwrap();
95        let ptr = re
96            .lea_mut(self.offset() as usize, size_of::<T>())
97            .unwrap()
98            .cast();
99        Ok((ptr, Some(re)))
100    }
101
102    pub fn null() -> Self {
103        Self::from_raw_parts(0, 0)
104    }
105
106    pub fn is_null(&self) -> bool {
107        self.offset() == 0
108    }
109
110    pub fn from_raw_parts(idx: u32, offset: u64) -> Self {
111        Self {
112            value: ((idx as u64) << 48) | offset,
113            _pse: PhantomStoreEffect,
114            _pd: PhantomData,
115        }
116    }
117
118    pub fn set(&mut self, gp: impl Into<GlobalPtr<T>>) -> crate::Result<()> {
119        let tx = Self::get_this(self);
120        *self = Self::new(tx, gp)?;
121        Ok(())
122    }
123
124    #[inline(always)]
125    pub fn fot_index(&self) -> u64 {
126        self.value >> 48
127    }
128
129    #[inline(always)]
130    pub fn is_local(&self) -> bool {
131        self.fot_index() == 0
132    }
133
134    #[inline(always)]
135    pub fn offset(&self) -> u64 {
136        self.value & ((1 << 48) - 1)
137    }
138
139    #[inline]
140    pub fn raw(&self) -> u64 {
141        self.value
142    }
143
144    pub fn new(tx: impl AsRef<ObjectHandle>, gp: impl Into<GlobalPtr<T>>) -> crate::Result<Self> {
145        let gp = gp.into();
146        let tx = tx.as_ref();
147        if gp.id() == tx.id() {
148            return Ok(Self::from_raw_parts(0, gp.offset()));
149        }
150        let fote: FotEntry = gp.into();
151        let fote =
152            twizzler_rt_abi::object::twz_rt_insert_fot(&tx, (&fote as *const FotEntry).cast())?;
153        Ok(Self::from_raw_parts(fote, gp.offset()))
154    }
155}