diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-10-31 07:35:48 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-10-31 07:35:48 +0100 |
commit | 639409a4ac8e1578ce34715338c6a4ddf9941294 (patch) | |
tree | 7231da4ebe348140a1ee4eb54b8e35c33bf3ac4d /rust/kernel/sync | |
parent | Merge tag 'rust-6.7' of https://github.com/Rust-for-Linux/linux (diff) | |
parent | rust: workqueue: add examples (diff) | |
download | linux-639409a4ac8e1578ce34715338c6a4ddf9941294.tar.xz linux-639409a4ac8e1578ce34715338c6a4ddf9941294.zip |
Merge tag 'wq-for-6.7-rust-bindings' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
Pull workqueue rust bindings from Tejun Heo:
"Add rust bindings to allow rust code to schedule work items on
workqueues.
While the current bindings don't cover all of the workqueue API, it
provides enough for basic usage and can be expanded as needed"
* tag 'wq-for-6.7-rust-bindings' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq:
rust: workqueue: add examples
rust: workqueue: add `try_spawn` helper method
rust: workqueue: implement `WorkItemPointer` for pointer types
rust: workqueue: add helper for defining work_struct fields
rust: workqueue: define built-in queues
rust: workqueue: add low-level workqueue bindings
rust: sync: add `Arc::{from_raw, into_raw}`
Diffstat (limited to 'rust/kernel/sync')
-rw-r--r-- | rust/kernel/sync/arc.rs | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index 7f04e4f00a2c..77cdbcf7bd2e 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -24,13 +24,13 @@ use crate::{ }; use alloc::boxed::Box; use core::{ - alloc::AllocError, + alloc::{AllocError, Layout}, fmt, marker::{PhantomData, Unsize}, mem::{ManuallyDrop, MaybeUninit}, ops::{Deref, DerefMut}, pin::Pin, - ptr::NonNull, + ptr::{NonNull, Pointee}, }; use macros::pin_data; @@ -215,6 +215,48 @@ impl<T: ?Sized> Arc<T> { } } + /// Convert the [`Arc`] into a raw pointer. + /// + /// The raw pointer has ownership of the refcount that this Arc object owned. + pub fn into_raw(self) -> *const T { + let ptr = self.ptr.as_ptr(); + core::mem::forget(self); + // SAFETY: The pointer is valid. + unsafe { core::ptr::addr_of!((*ptr).data) } + } + + /// Recreates an [`Arc`] instance previously deconstructed via [`Arc::into_raw`]. + /// + /// # Safety + /// + /// `ptr` must have been returned by a previous call to [`Arc::into_raw`]. Additionally, it + /// must not be called more than once for each previous call to [`Arc::into_raw`]. + pub unsafe fn from_raw(ptr: *const T) -> Self { + let refcount_layout = Layout::new::<bindings::refcount_t>(); + // SAFETY: The caller guarantees that the pointer is valid. + let val_layout = Layout::for_value(unsafe { &*ptr }); + // SAFETY: We're computing the layout of a real struct that existed when compiling this + // binary, so its layout is not so large that it can trigger arithmetic overflow. + let val_offset = unsafe { refcount_layout.extend(val_layout).unwrap_unchecked().1 }; + + let metadata: <T as Pointee>::Metadata = core::ptr::metadata(ptr); + // SAFETY: The metadata of `T` and `ArcInner<T>` is the same because `ArcInner` is a struct + // with `T` as its last field. + // + // This is documented at: + // <https://doc.rust-lang.org/std/ptr/trait.Pointee.html>. + let metadata: <ArcInner<T> as Pointee>::Metadata = + unsafe { core::mem::transmute_copy(&metadata) }; + // SAFETY: The pointer is in-bounds of an allocation both before and after offsetting the + // pointer, since it originates from a previous call to `Arc::into_raw` and is still valid. + let ptr = unsafe { (ptr as *mut u8).sub(val_offset) as *mut () }; + let ptr = core::ptr::from_raw_parts_mut(ptr, metadata); + + // SAFETY: By the safety requirements we know that `ptr` came from `Arc::into_raw`, so the + // reference count held then will be owned by the new `Arc` object. + unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) } + } + /// Returns an [`ArcBorrow`] from the given [`Arc`]. /// /// This is useful when the argument of a function call is an [`ArcBorrow`] (e.g., in a method |