Skip to content

Commit b906dc9

Browse files
Danilo Krummrichojeda
authored andcommitted
rust: types: implement ForeignOwnable for ARef<T>
Implement ForeignOwnable for ARef<T>, making it possible for C code to own an ARef<T>. Since ARef represents shared ownership, BorrowedMut is &T rather than &mut T, matching the semantics of the underlying reference-counted type. Signed-off-by: Danilo Krummrich <dakr@kernel.org> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Tested-by: Daniel Almeida <daniel.almeida@collabora.com> Signed-off-by: Philipp Stanner <phasta@kernel.org> Acked-by: Danilo Krummrich <dakr@kernel.org> Link: https://patch.msgid.link/20260805145949.938505-4-phasta@kernel.org [ Relaxed `'static` bound and added `#[inline]` as discussed. Added submitter's Signed-off-by. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
1 parent 496b695 commit b906dc9

1 file changed

Lines changed: 50 additions & 0 deletions

File tree

‎rust/kernel/sync/aref.rs‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ use core::{
2424
ptr::NonNull, //
2525
};
2626

27+
use crate::{
28+
prelude::*,
29+
types::ForeignOwnable, //
30+
};
31+
2732
/// Types that are _always_ reference counted.
2833
///
2934
/// It allows such types to define their own custom ref increment and decrement functions.
@@ -188,6 +193,51 @@ where
188193
}
189194
impl<T: AlwaysRefCounted + Eq> Eq for ARef<T> {}
190195

196+
// SAFETY: `into_foreign` returns a pointer from `NonNull::as_ptr`, so it's non-null. The
197+
// `ARef` invariant guarantees that `ptr` points to a valid `T`, so it's aligned to `T`.
198+
unsafe impl<T: AlwaysRefCounted> ForeignOwnable for ARef<T> {
199+
const FOREIGN_ALIGN: usize = core::mem::align_of::<T>();
200+
201+
type Borrowed<'a>
202+
= &'a T
203+
where
204+
Self: 'a;
205+
type BorrowedMut<'a>
206+
= &'a T
207+
where
208+
Self: 'a;
209+
210+
#[inline]
211+
fn into_foreign(self) -> *mut c_void {
212+
ARef::into_raw(self).as_ptr().cast()
213+
}
214+
215+
#[inline]
216+
unsafe fn from_foreign(ptr: *mut c_void) -> Self {
217+
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
218+
// call to `Self::into_foreign`.
219+
let ptr = unsafe { NonNull::new_unchecked(ptr.cast()) };
220+
221+
// SAFETY: `ptr` came from `into_foreign`, which consumed an `ARef` without decrementing
222+
// the refcount, so we can transfer the ownership to the new `ARef`.
223+
unsafe { ARef::from_raw(ptr) }
224+
}
225+
226+
#[inline]
227+
unsafe fn borrow<'a>(ptr: *mut c_void) -> &'a T {
228+
// SAFETY: The safety requirements of this method ensure that the object remains alive and
229+
// immutable for the duration of 'a.
230+
unsafe { &*ptr.cast() }
231+
}
232+
233+
#[inline]
234+
unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> &'a T {
235+
// SAFETY: The safety requirements for `borrow_mut` are a superset of the safety
236+
// requirements for `borrow`.
237+
unsafe { <Self as ForeignOwnable>::borrow(ptr) }
238+
}
239+
}
240+
191241
impl<T, U> PartialEq<&'_ U> for ARef<T>
192242
where
193243
T: AlwaysRefCounted + PartialEq<U>,

0 commit comments

Comments
 (0)