twizzler/ptr/
invariant.rs1use 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}