kernel_api/syscall/
handle_inner.rs1use alloc::sync::Arc;
2use core::fmt;
3use core::mem::ManuallyDrop;
4use core::sync::atomic::{AtomicI64, AtomicPtr, AtomicU64, Ordering};
5use lf_radix_tree::LockFreeRadixTreeU32L4;
6use crate::memory::EpochGuard;
7use crate::ptr::TaggedNonNull;
8use crate::syscall;
9use crate::syscall::Error;
10use crate::threading::TaskRef;
11
12#[derive(Debug)]
15pub struct HandleMap(AtomicPtr<HandleMapInner>);
16
17struct HandleMapInner {
18 map: LockFreeRadixTreeU32L4<Handle>,
19 bump_free: AtomicU64,
21 free_stack_top: AtomicI64,
29}
30
31impl HandleMap {
32 fn deref<'ebr>(&self, _ebr: &'ebr EpochGuard) -> &'ebr HandleMapInner {
33 let ptr = self.0.load(Ordering::Acquire).cast_const();
34 unsafe { &*ptr }
37 }
38
39 pub fn clone(&self, _ebr: &EpochGuard) -> Self {
40 let ptr = self.0.load(Ordering::Acquire).cast_const();
41 unsafe { Arc::increment_strong_count(ptr) };
44 Self(AtomicPtr::new(ptr.cast_mut()))
45 }
46
47 #[must_use]
55 pub fn new() -> Self {
56 let this = HandleMapInner {
57 map: LockFreeRadixTreeU32L4::new(),
58 bump_free: AtomicU64::new(0),
59 free_stack_top: AtomicI64::new(-1),
60 };
61 let arc = Arc::new(this);
62 Self(AtomicPtr::new(Arc::into_raw(arc).cast_mut()))
63 }
64
65 pub fn push(&self, handle: Arc<Handle>, ebr: &EpochGuard) -> syscall::Result<u32> {
74 self.transfer(PoppedHandle(Arc::into_raw(handle)), ebr)
75 }
76
77 pub fn transfer(&self, handle: PoppedHandle, ebr: &EpochGuard) -> syscall::Result<u32> {
87 let this = self.deref(ebr);
88 let val = {
89 let mut stack_top = this.free_stack_top.load(Ordering::Acquire);
90 loop {
91 if stack_top < 0 {
94 let val = this.bump_free.fetch_add(1, Ordering::Relaxed);
95 break u32::try_from(val).map_err(|_| {
96 this.bump_free.fetch_sub(1, Ordering::Relaxed);
97 Error::Overflow
98 })?
99 } else {
100 let val = stack_top as u32;
101 let next = unsafe { this.map.get(val).unwrap_unchecked() }
103 .load(Ordering::Acquire)
104 .addr();
105 match this.free_stack_top.compare_exchange_weak(
106 stack_top,
107 next as i64,
108 Ordering::AcqRel,
109 Ordering::Acquire,
110 ) {
111 Ok(_) => break val,
112 Err(updated) => stack_top = updated,
113 }
114 }
115 }
116 };
117 let handle = ManuallyDrop::new(handle);
118 this.map.insert(val, handle.0.cast_mut()).expect("val from free list must be free");
119 Ok(val)
120 }
121
122 pub fn get<'ebr>(&self, val: u32, ebr: &'ebr EpochGuard) -> syscall::Result<&'ebr Handle> {
128 let this = self.deref(ebr);
129 this.map.get(val)
130 .and_then(|ptr| unsafe { ptr.load(Ordering::Acquire).as_ref() })
133 .ok_or(Error::InvalidHandle)
134 }
135
136 #[inline]
145 pub fn pop(&self, val: u32, ebr: &EpochGuard) -> syscall::Result<PoppedHandle> {
146 let this = self.deref(ebr);
147 let ptr = this.map.get(val).ok_or(Error::InvalidHandle)?;
148 let ptr = ptr.swap(core::ptr::null_mut(), Ordering::AcqRel).cast_const();
149 if ptr.is_null() { return Err(Error::InvalidHandle); }
150 Ok(PoppedHandle(ptr))
151 }
152
153 pub fn close(&self, val: u32, ebr: &EpochGuard) -> syscall::Result<()> {
154 self.pop(val, ebr).map(drop)
155 }
156
157 #[must_use]
169 pub fn swap(&self, other: Self) -> Self {
170 let mut other = ManuallyDrop::new(other);
171 let other_ptr = *other.0.get_mut();
172 let old = self.0.swap(other_ptr, Ordering::AcqRel);
173 Self(AtomicPtr::new(old))
174 }
175}
176
177impl Default for HandleMap {
178 fn default() -> Self {
179 Self::new()
180 }
181}
182
183impl Drop for HandleMap {
184 fn drop(&mut self) {
185 let inner = *self.0.get_mut();
186 crate::bridge::ebr::defer_and_cleanup(
187 |ptr| unsafe { drop(Arc::<HandleMapInner>::from_raw(ptr.cast_const().cast())) },
190 inner.cast(),
191 );
192 }
193}
194
195union Object {
196 oid: u32,
197 koid: TaggedNonNull<u64>,
198}
199
200unsafe impl Sync for Object {}
201unsafe impl Send for Object {}
202
203pub struct Handle {
205 endpoint: Option<TaskRef>,
206 object: Object,
207}
208
209impl Handle {
210 pub fn new(endpoint: TaskRef, oid: u32) -> Arc<Self> {
212 Arc::new(Self {
213 endpoint: Some(endpoint),
214 object: Object { oid },
215 })
216 }
217
218 pub fn new_system(koid: TaggedNonNull<u64>) -> Arc<Self> {
220 Arc::new(Self {
221 endpoint: None,
222 object: Object { koid },
223 })
224 }
225
226 #[inline]
228 pub fn oid(&self) -> u32 {
229 assert!(!self.is_system(), "cannot get `oid` for system handle");
230 unsafe { self.object.oid }
232 }
233
234 #[inline]
236 pub fn koid(&self) -> TaggedNonNull<u64> {
237 assert!(self.is_system(), "cannot get `koid` for non-system handle");
238 unsafe { self.object.koid }
240 }
241
242 #[inline]
244 pub fn target(&self) -> TaskRef {
245 self.endpoint.expect("cannot get endpoint of system handle")
246 }
247
248 #[inline]
250 pub fn is_system(&self) -> bool {
251 self.endpoint.is_none()
252 }
253}
254
255impl fmt::Debug for Handle {
256 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257 let mut f = f.debug_struct("Handle");
258
259 if self.is_system() {
260 f.field("koid", &self.koid());
261 } else {
262 f.field("endpoint", &self.target())
263 .field("oid", &self.oid());
264 }
265
266 f.finish()
267 }
268}
269
270#[repr(transparent)]
277pub struct PoppedHandle(*const Handle);
278
279impl PoppedHandle {
280 #[must_use = "dropping PoppedHandle directly cleans up the contained Handle without paying refcount costs"]
281 pub fn to_arc(self) -> Arc<Handle> {
282 unsafe { Arc::increment_strong_count(self.0) };
284 unsafe { Arc::from_raw(self.0) }
286 }
287}
288
289impl Drop for PoppedHandle {
290 fn drop(&mut self) {
291 crate::bridge::ebr::defer_and_cleanup(
292 |ptr| unsafe { drop(Arc::<Handle>::from_raw(ptr.cast_const().cast())) },
295 self.0.cast_mut().cast(),
296 );
297 }
298}