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