summaryrefslogtreecommitdiff
path: root/rust/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'rust/kernel')
-rw-r--r--rust/kernel/alloc/allocator.rs1
-rw-r--r--rust/kernel/alloc/kbox.rs13
-rw-r--r--rust/kernel/block/mq/request.rs4
-rw-r--r--rust/kernel/block/mq/tag_set.rs5
-rw-r--r--rust/kernel/cred.rs5
-rw-r--r--rust/kernel/dma.rs391
-rw-r--r--rust/kernel/driver.rs6
-rw-r--r--rust/kernel/error.rs124
-rw-r--r--rust/kernel/firmware.rs216
-rw-r--r--rust/kernel/fs/file.rs8
-rw-r--r--rust/kernel/init.rs1447
-rw-r--r--rust/kernel/init/__internal.rs264
-rw-r--r--rust/kernel/init/macros.rs1410
-rw-r--r--rust/kernel/kunit.rs171
-rw-r--r--rust/kernel/lib.rs9
-rw-r--r--rust/kernel/list.rs473
-rw-r--r--rust/kernel/net/phy.rs4
-rw-r--r--rust/kernel/pci.rs2
-rw-r--r--rust/kernel/platform.rs2
-rw-r--r--rust/kernel/prelude.rs8
-rw-r--r--rust/kernel/print.rs10
-rw-r--r--rust/kernel/rbtree.rs12
-rw-r--r--rust/kernel/security.rs12
-rw-r--r--rust/kernel/seq_file.rs3
-rw-r--r--rust/kernel/str.rs46
-rw-r--r--rust/kernel/sync.rs58
-rw-r--r--rust/kernel/sync/arc.rs81
-rw-r--r--rust/kernel/sync/condvar.rs34
-rw-r--r--rust/kernel/sync/lock.rs40
-rw-r--r--rust/kernel/sync/lock/global.rs5
-rw-r--r--rust/kernel/sync/lock/mutex.rs2
-rw-r--r--rust/kernel/sync/lock/spinlock.rs2
-rw-r--r--rust/kernel/sync/poll.rs6
-rw-r--r--rust/kernel/task.rs4
-rw-r--r--rust/kernel/time.rs68
-rw-r--r--rust/kernel/time/hrtimer.rs520
-rw-r--r--rust/kernel/time/hrtimer/arc.rs100
-rw-r--r--rust/kernel/time/hrtimer/pin.rs104
-rw-r--r--rust/kernel/time/hrtimer/pin_mut.rs108
-rw-r--r--rust/kernel/time/hrtimer/tbox.rs120
-rw-r--r--rust/kernel/types.rs23
-rw-r--r--rust/kernel/uaccess.rs3
-rw-r--r--rust/kernel/workqueue.rs20
43 files changed, 2798 insertions, 3146 deletions
diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs
index 439985e29fbc..aa2dfa9dca4c 100644
--- a/rust/kernel/alloc/allocator.rs
+++ b/rust/kernel/alloc/allocator.rs
@@ -80,6 +80,7 @@ impl ReallocFunc {
/// This method has the same guarantees as `Allocator::realloc`. Additionally
/// - it accepts any pointer to a valid memory allocation allocated by this function.
/// - memory allocated by this function remains valid until it is passed to this function.
+ #[inline]
unsafe fn call(
&self,
ptr: Option<NonNull<u8>>,
diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index cb4ebea3b074..b77d32f3a58b 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -15,8 +15,9 @@ use core::pin::Pin;
use core::ptr::NonNull;
use core::result::Result;
-use crate::init::{InPlaceInit, InPlaceWrite, Init, PinInit};
+use crate::init::InPlaceInit;
use crate::types::ForeignOwnable;
+use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption};
/// The kernel's [`Box`] type -- a heap allocation for a single value of type `T`.
///
@@ -99,6 +100,10 @@ pub type VBox<T> = Box<T, super::allocator::Vmalloc>;
/// ```
pub type KVBox<T> = Box<T, super::allocator::KVmalloc>;
+// SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee:
+// https://doc.rust-lang.org/stable/std/option/index.html#representation).
+unsafe impl<T, A: Allocator> ZeroableOption for Box<T, A> {}
+
// SAFETY: `Box` is `Send` if `T` is `Send` because the `Box` owns a `T`.
unsafe impl<T, A> Send for Box<T, A>
where
@@ -245,6 +250,12 @@ where
Ok(Self::new(x, flags)?.into())
}
+ /// Convert a [`Box<T,A>`] to a [`Pin<Box<T,A>>`]. If `T` does not implement
+ /// [`Unpin`], then `x` will be pinned in memory and can't be moved.
+ pub fn into_pin(this: Self) -> Pin<Self> {
+ this.into()
+ }
+
/// Forgets the contents (does not run the destructor), but keeps the allocation.
fn forget_contents(this: Self) -> Box<MaybeUninit<T>, A> {
let ptr = Self::into_raw(this);
diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
index 7943f43b9575..4a5b7ec914ef 100644
--- a/rust/kernel/block/mq/request.rs
+++ b/rust/kernel/block/mq/request.rs
@@ -12,7 +12,7 @@ use crate::{
};
use core::{
marker::PhantomData,
- ptr::{addr_of_mut, NonNull},
+ ptr::NonNull,
sync::atomic::{AtomicU64, Ordering},
};
@@ -187,7 +187,7 @@ impl RequestDataWrapper {
pub(crate) unsafe fn refcount_ptr(this: *mut Self) -> *mut AtomicU64 {
// SAFETY: Because of the safety requirements of this function, the
// field projection is safe.
- unsafe { addr_of_mut!((*this).refcount) }
+ unsafe { &raw mut (*this).refcount }
}
}
diff --git a/rust/kernel/block/mq/tag_set.rs b/rust/kernel/block/mq/tag_set.rs
index 00ddcc71dfa2..bcf4214ad149 100644
--- a/rust/kernel/block/mq/tag_set.rs
+++ b/rust/kernel/block/mq/tag_set.rs
@@ -10,12 +10,11 @@ use crate::{
bindings,
block::mq::{operations::OperationsVTable, request::RequestDataWrapper, Operations},
error,
- prelude::PinInit,
- try_pin_init,
+ prelude::try_pin_init,
types::Opaque,
};
use core::{convert::TryInto, marker::PhantomData};
-use macros::{pin_data, pinned_drop};
+use pin_init::{pin_data, pinned_drop, PinInit};
/// A wrapper for the C `struct blk_mq_tag_set`.
///
diff --git a/rust/kernel/cred.rs b/rust/kernel/cred.rs
index 81d67789b16f..2599f01e8b28 100644
--- a/rust/kernel/cred.rs
+++ b/rust/kernel/cred.rs
@@ -47,6 +47,7 @@ impl Credential {
///
/// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the
/// returned [`Credential`] reference.
+ #[inline]
pub unsafe fn from_ptr<'a>(ptr: *const bindings::cred) -> &'a Credential {
// SAFETY: The safety requirements guarantee the validity of the dereference, while the
// `Credential` type being transparent makes the cast ok.
@@ -54,6 +55,7 @@ impl Credential {
}
/// Get the id for this security context.
+ #[inline]
pub fn get_secid(&self) -> u32 {
let mut secid = 0;
// SAFETY: The invariants of this type ensures that the pointer is valid.
@@ -62,6 +64,7 @@ impl Credential {
}
/// Returns the effective UID of the given credential.
+ #[inline]
pub fn euid(&self) -> Kuid {
// SAFETY: By the type invariant, we know that `self.0` is valid. Furthermore, the `euid`
// field of a credential is never changed after initialization, so there is no potential
@@ -72,11 +75,13 @@ impl Credential {
// SAFETY: The type invariants guarantee that `Credential` is always ref-counted.
unsafe impl AlwaysRefCounted for Credential {
+ #[inline]
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
unsafe { bindings::get_cred(self.0.get()) };
}
+ #[inline]
unsafe fn dec_ref(obj: core::ptr::NonNull<Credential>) {
// SAFETY: The safety requirements guarantee that the refcount is nonzero. The cast is okay
// because `Credential` has the same representation as `struct cred`.
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
new file mode 100644
index 000000000000..8cdc76043ee7
--- /dev/null
+++ b/rust/kernel/dma.rs
@@ -0,0 +1,391 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Direct memory access (DMA).
+//!
+//! C header: [`include/linux/dma-mapping.h`](srctree/include/linux/dma-mapping.h)
+
+use crate::{
+ bindings, build_assert,
+ device::Device,
+ error::code::*,
+ error::Result,
+ transmute::{AsBytes, FromBytes},
+ types::ARef,
+};
+
+/// Possible attributes associated with a DMA mapping.
+///
+/// They can be combined with the operators `|`, `&`, and `!`.
+///
+/// Values can be used from the [`attrs`] module.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::device::Device;
+/// use kernel::dma::{attrs::*, CoherentAllocation};
+///
+/// # fn test(dev: &Device) -> Result {
+/// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN;
+/// let c: CoherentAllocation<u64> =
+/// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, attribs)?;
+/// # Ok::<(), Error>(()) }
+/// ```
+#[derive(Clone, Copy, PartialEq)]
+#[repr(transparent)]
+pub struct Attrs(u32);
+
+impl Attrs {
+ /// Get the raw representation of this attribute.
+ pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
+ self.0 as _
+ }
+
+ /// Check whether `flags` is contained in `self`.
+ pub fn contains(self, flags: Attrs) -> bool {
+ (self & flags) == flags
+ }
+}
+
+impl core::ops::BitOr for Attrs {
+ type Output = Self;
+ fn bitor(self, rhs: Self) -> Self::Output {
+ Self(self.0 | rhs.0)
+ }
+}
+
+impl core::ops::BitAnd for Attrs {
+ type Output = Self;
+ fn bitand(self, rhs: Self) -> Self::Output {
+ Self(self.0 & rhs.0)
+ }
+}
+
+impl core::ops::Not for Attrs {
+ type Output = Self;
+ fn not(self) -> Self::Output {
+ Self(!self.0)
+ }
+}
+
+/// DMA mapping attributes.
+pub mod attrs {
+ use super::Attrs;
+
+ /// Specifies that reads and writes to the mapping may be weakly ordered, that is that reads
+ /// and writes may pass each other.
+ pub const DMA_ATTR_WEAK_ORDERING: Attrs = Attrs(bindings::DMA_ATTR_WEAK_ORDERING);
+
+ /// Specifies that writes to the mapping may be buffered to improve performance.
+ pub const DMA_ATTR_WRITE_COMBINE: Attrs = Attrs(bindings::DMA_ATTR_WRITE_COMBINE);
+
+ /// Lets the platform to avoid creating a kernel virtual mapping for the allocated buffer.
+ pub const DMA_ATTR_NO_KERNEL_MAPPING: Attrs = Attrs(bindings::DMA_ATTR_NO_KERNEL_MAPPING);
+
+ /// Allows platform code to skip synchronization of the CPU cache for the given buffer assuming
+ /// that it has been already transferred to 'device' domain.
+ pub const DMA_ATTR_SKIP_CPU_SYNC: Attrs = Attrs(bindings::DMA_ATTR_SKIP_CPU_SYNC);
+
+ /// Forces contiguous allocation of the buffer in physical memory.
+ pub const DMA_ATTR_FORCE_CONTIGUOUS: Attrs = Attrs(bindings::DMA_ATTR_FORCE_CONTIGUOUS);
+
+ /// This is a hint to the DMA-mapping subsystem that it's probably not worth the time to try
+ /// to allocate memory to in a way that gives better TLB efficiency.
+ pub const DMA_ATTR_ALLOC_SINGLE_PAGES: Attrs = Attrs(bindings::DMA_ATTR_ALLOC_SINGLE_PAGES);
+
+ /// This tells the DMA-mapping subsystem to suppress allocation failure reports (similarly to
+ /// __GFP_NOWARN).
+ pub const DMA_ATTR_NO_WARN: Attrs = Attrs(bindings::DMA_ATTR_NO_WARN);
+
+ /// Used to indicate that the buffer is fully accessible at an elevated privilege level (and
+ /// ideally inaccessible or at least read-only at lesser-privileged levels).
+ pub const DMA_ATTR_PRIVILEGED: Attrs = Attrs(bindings::DMA_ATTR_PRIVILEGED);
+}
+
+/// An abstraction of the `dma_alloc_coherent` API.
+///
+/// This is an abstraction around the `dma_alloc_coherent` API which is used to allocate and map
+/// large consistent DMA regions.
+///
+/// A [`CoherentAllocation`] instance contains a pointer to the allocated region (in the
+/// processor's virtual address space) and the device address which can be given to the device
+/// as the DMA address base of the region. The region is released once [`CoherentAllocation`]
+/// is dropped.
+///
+/// # Invariants
+///
+/// For the lifetime of an instance of [`CoherentAllocation`], the `cpu_addr` is a valid pointer
+/// to an allocated region of consistent memory and `dma_handle` is the DMA address base of
+/// the region.
+// TODO
+//
+// DMA allocations potentially carry device resources (e.g.IOMMU mappings), hence for soundness
+// reasons DMA allocation would need to be embedded in a `Devres` container, in order to ensure
+// that device resources can never survive device unbind.
+//
+// However, it is neither desirable nor necessary to protect the allocated memory of the DMA
+// allocation from surviving device unbind; it would require RCU read side critical sections to
+// access the memory, which may require subsequent unnecessary copies.
+//
+// Hence, find a way to revoke the device resources of a `CoherentAllocation`, but not the
+// entire `CoherentAllocation` including the allocated memory itself.
+pub struct CoherentAllocation<T: AsBytes + FromBytes> {
+ dev: ARef<Device>,
+ dma_handle: bindings::dma_addr_t,
+ count: usize,
+ cpu_addr: *mut T,
+ dma_attrs: Attrs,
+}
+
+impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
+ /// Allocates a region of `size_of::<T> * count` of consistent memory.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use kernel::device::Device;
+ /// use kernel::dma::{attrs::*, CoherentAllocation};
+ ///
+ /// # fn test(dev: &Device) -> Result {
+ /// let c: CoherentAllocation<u64> =
+ /// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
+ /// # Ok::<(), Error>(()) }
+ /// ```
+ pub fn alloc_attrs(
+ dev: &Device,
+ count: usize,
+ gfp_flags: kernel::alloc::Flags,
+ dma_attrs: Attrs,
+ ) -> Result<CoherentAllocation<T>> {
+ build_assert!(
+ core::mem::size_of::<T>() > 0,
+ "It doesn't make sense for the allocated type to be a ZST"
+ );
+
+ let size = count
+ .checked_mul(core::mem::size_of::<T>())
+ .ok_or(EOVERFLOW)?;
+ let mut dma_handle = 0;
+ // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
+ let ret = unsafe {
+ bindings::dma_alloc_attrs(
+ dev.as_raw(),
+ size,
+ &mut dma_handle,
+ gfp_flags.as_raw(),
+ dma_attrs.as_raw(),
+ )
+ };
+ if ret.is_null() {
+ return Err(ENOMEM);
+ }
+ // INVARIANT: We just successfully allocated a coherent region which is accessible for
+ // `count` elements, hence the cpu address is valid. We also hold a refcounted reference
+ // to the device.
+ Ok(Self {
+ dev: dev.into(),
+ dma_handle,
+ count,
+ cpu_addr: ret as *mut T,
+ dma_attrs,
+ })
+ }
+
+ /// Performs the same functionality as [`CoherentAllocation::alloc_attrs`], except the
+ /// `dma_attrs` is 0 by default.
+ pub fn alloc_coherent(
+ dev: &Device,
+ count: usize,
+ gfp_flags: kernel::alloc::Flags,
+ ) -> Result<CoherentAllocation<T>> {
+ CoherentAllocation::alloc_attrs(dev, count, gfp_flags, Attrs(0))
+ }
+
+ /// Returns the base address to the allocated region in the CPU's virtual address space.
+ pub fn start_ptr(&self) -> *const T {
+ self.cpu_addr
+ }
+
+ /// Returns the base address to the allocated region in the CPU's virtual address space as
+ /// a mutable pointer.
+ pub fn start_ptr_mut(&mut self) -> *mut T {
+ self.cpu_addr
+ }
+
+ /// Returns a DMA handle which may given to the device as the DMA address base of
+ /// the region.
+ pub fn dma_handle(&self) -> bindings::dma_addr_t {
+ self.dma_handle
+ }
+
+ /// Returns a pointer to an element from the region with bounds checking. `offset` is in
+ /// units of `T`, not the number of bytes.
+ ///
+ /// Public but hidden since it should only be used from [`dma_read`] and [`dma_write`] macros.
+ #[doc(hidden)]
+ pub fn item_from_index(&self, offset: usize) -> Result<*mut T> {
+ if offset >= self.count {
+ return Err(EINVAL);
+ }
+ // SAFETY:
+ // - The pointer is valid due to type invariant on `CoherentAllocation`
+ // and we've just checked that the range and index is within bounds.
+ // - `offset` can't overflow since it is smaller than `self.count` and we've checked
+ // that `self.count` won't overflow early in the constructor.
+ Ok(unsafe { self.cpu_addr.add(offset) })
+ }
+
+ /// Reads the value of `field` and ensures that its type is [`FromBytes`].
+ ///
+ /// # Safety
+ ///
+ /// This must be called from the [`dma_read`] macro which ensures that the `field` pointer is
+ /// validated beforehand.
+ ///
+ /// Public but hidden since it should only be used from [`dma_read`] macro.
+ #[doc(hidden)]
+ pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
+ // SAFETY:
+ // - By the safety requirements field is valid.
+ // - Using read_volatile() here is not sound as per the usual rules, the usage here is
+ // a special exception with the following notes in place. When dealing with a potential
+ // race from a hardware or code outside kernel (e.g. user-space program), we need that
+ // read on a valid memory is not UB. Currently read_volatile() is used for this, and the
+ // rationale behind is that it should generate the same code as READ_ONCE() which the
+ // kernel already relies on to avoid UB on data races. Note that the usage of
+ // read_volatile() is limited to this particular case, it cannot be used to prevent
+ // the UB caused by racing between two kernel functions nor do they provide atomicity.
+ unsafe { field.read_volatile() }
+ }
+
+ /// Writes a value to `field` and ensures that its type is [`AsBytes`].
+ ///
+ /// # Safety
+ ///
+ /// This must be called from the [`dma_write`] macro which ensures that the `field` pointer is
+ /// validated beforehand.
+ ///
+ /// Public but hidden since it should only be used from [`dma_write`] macro.
+ #[doc(hidden)]
+ pub unsafe fn field_write<F: AsBytes>(&self, field: *mut F, val: F) {
+ // SAFETY:
+ // - By the safety requirements field is valid.
+ // - Using write_volatile() here is not sound as per the usual rules, the usage here is
+ // a special exception with the following notes in place. When dealing with a potential
+ // race from a hardware or code outside kernel (e.g. user-space program), we need that
+ // write on a valid memory is not UB. Currently write_volatile() is used for this, and the
+ // rationale behind is that it should generate the same code as WRITE_ONCE() which the
+ // kernel already relies on to avoid UB on data races. Note that the usage of
+ // write_volatile() is limited to this particular case, it cannot be used to prevent
+ // the UB caused by racing between two kernel functions nor do they provide atomicity.
+ unsafe { field.write_volatile(val) }
+ }
+}
+
+/// Note that the device configured to do DMA must be halted before this object is dropped.
+impl<T: AsBytes + FromBytes> Drop for CoherentAllocation<T> {
+ fn drop(&mut self) {
+ let size = self.count * core::mem::size_of::<T>();
+ // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
+ // The cpu address, and the dma handle are valid due to the type invariants on
+ // `CoherentAllocation`.
+ unsafe {
+ bindings::dma_free_attrs(
+ self.dev.as_raw(),
+ size,
+ self.cpu_addr as _,
+ self.dma_handle,
+ self.dma_attrs.as_raw(),
+ )
+ }
+ }
+}
+
+// SAFETY: It is safe to send a `CoherentAllocation` to another thread if `T`
+// can be sent to another thread.
+unsafe impl<T: AsBytes + FromBytes + Send> Send for CoherentAllocation<T> {}
+
+/// Reads a field of an item from an allocated region of structs.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::device::Device;
+/// use kernel::dma::{attrs::*, CoherentAllocation};
+///
+/// struct MyStruct { field: u32, }
+///
+/// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
+/// unsafe impl kernel::transmute::FromBytes for MyStruct{};
+/// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
+/// unsafe impl kernel::transmute::AsBytes for MyStruct{};
+///
+/// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result {
+/// let whole = kernel::dma_read!(alloc[2]);
+/// let field = kernel::dma_read!(alloc[1].field);
+/// # Ok::<(), Error>(()) }
+/// ```
+#[macro_export]
+macro_rules! dma_read {
+ ($dma:expr, $idx: expr, $($field:tt)*) => {{
+ let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
+ // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be
+ // dereferenced. The compiler also further validates the expression on whether `field`
+ // is a member of `item` when expanded by the macro.
+ unsafe {
+ let ptr_field = ::core::ptr::addr_of!((*item) $($field)*);
+ $crate::dma::CoherentAllocation::field_read(&$dma, ptr_field)
+ }
+ }};
+ ($dma:ident [ $idx:expr ] $($field:tt)* ) => {
+ $crate::dma_read!($dma, $idx, $($field)*);
+ };
+ ($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => {
+ $crate::dma_read!($($dma).*, $idx, $($field)*);
+ };
+}
+
+/// Writes to a field of an item from an allocated region of structs.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::device::Device;
+/// use kernel::dma::{attrs::*, CoherentAllocation};
+///
+/// struct MyStruct { member: u32, }
+///
+/// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
+/// unsafe impl kernel::transmute::FromBytes for MyStruct{};
+/// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
+/// unsafe impl kernel::transmute::AsBytes for MyStruct{};
+///
+/// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result {
+/// kernel::dma_write!(alloc[2].member = 0xf);
+/// kernel::dma_write!(alloc[1] = MyStruct { member: 0xf });
+/// # Ok::<(), Error>(()) }
+/// ```
+#[macro_export]
+macro_rules! dma_write {
+ ($dma:ident [ $idx:expr ] $($field:tt)*) => {{
+ $crate::dma_write!($dma, $idx, $($field)*);
+ }};
+ ($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => {{
+ $crate::dma_write!($($dma).*, $idx, $($field)*);
+ }};
+ ($dma:expr, $idx: expr, = $val:expr) => {
+ let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
+ // SAFETY: `item_from_index` ensures that `item` is always a valid item.
+ unsafe { $crate::dma::CoherentAllocation::field_write(&$dma, item, $val) }
+ };
+ ($dma:expr, $idx: expr, $(.$field:ident)* = $val:expr) => {
+ let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
+ // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be
+ // dereferenced. The compiler also further validates the expression on whether `field`
+ // is a member of `item` when expanded by the macro.
+ unsafe {
+ let ptr_field = ::core::ptr::addr_of_mut!((*item) $(.$field)*);
+ $crate::dma::CoherentAllocation::field_write(&$dma, ptr_field, $val)
+ }
+ };
+}
diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs
index 2a16d5e64e6c..ec9166cedfa7 100644
--- a/rust/kernel/driver.rs
+++ b/rust/kernel/driver.rs
@@ -6,9 +6,9 @@
//! register using the [`Registration`] class.
use crate::error::{Error, Result};
-use crate::{device, init::PinInit, of, str::CStr, try_pin_init, types::Opaque, ThisModule};
+use crate::{device, of, str::CStr, try_pin_init, types::Opaque, ThisModule};
use core::pin::Pin;
-use macros::{pin_data, pinned_drop};
+use pin_init::{pin_data, pinned_drop, PinInit};
/// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform,
/// Amba, etc.) to provide the corresponding subsystem specific implementation to register /
@@ -114,7 +114,7 @@ macro_rules! module_driver {
impl $crate::InPlaceModule for DriverModule {
fn init(
module: &'static $crate::ThisModule
- ) -> impl $crate::init::PinInit<Self, $crate::error::Error> {
+ ) -> impl ::pin_init::PinInit<Self, $crate::error::Error> {
$crate::try_pin_init!(Self {
_driver <- $crate::driver::Registration::new(
<Self as $crate::ModuleMetadata>::NAME,
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index a194d83e6835..3dee3139fcd4 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -64,6 +64,7 @@ pub mod code {
declare_err!(EPIPE, "Broken pipe.");
declare_err!(EDOM, "Math argument out of domain of func.");
declare_err!(ERANGE, "Math result not representable.");
+ declare_err!(EOVERFLOW, "Value too large for defined data type.");
declare_err!(ERESTARTSYS, "Restart the system call.");
declare_err!(ERESTARTNOINTR, "System call was interrupted by a signal and will be restarted.");
declare_err!(ERESTARTNOHAND, "Restart if no handler.");
@@ -248,8 +249,129 @@ impl From<core::convert::Infallible> for Error {
/// [`Error`] as its error type.
///
/// Note that even if a function does not return anything when it succeeds,
-/// it should still be modeled as returning a `Result` rather than
+/// it should still be modeled as returning a [`Result`] rather than
/// just an [`Error`].
+///
+/// Calling a function that returns [`Result`] forces the caller to handle
+/// the returned [`Result`].
+///
+/// This can be done "manually" by using [`match`]. Using [`match`] to decode
+/// the [`Result`] is similar to C where all the return value decoding and the
+/// error handling is done explicitly by writing handling code for each
+/// error to cover. Using [`match`] the error and success handling can be
+/// implemented in all detail as required. For example (inspired by
+/// [`samples/rust/rust_minimal.rs`]):
+///
+/// ```
+/// # #[allow(clippy::single_match)]
+/// fn example() -> Result {
+/// let mut numbers = KVec::new();
+///
+/// match numbers.push(72, GFP_KERNEL) {
+/// Err(e) => {
+/// pr_err!("Error pushing 72: {e:?}");
+/// return Err(e.into());
+/// }
+/// // Do nothing, continue.
+/// Ok(()) => (),
+/// }
+///
+/// match numbers.push(108, GFP_KERNEL) {
+/// Err(e) => {
+/// pr_err!("Error pushing 108: {e:?}");
+/// return Err(e.into());
+/// }
+/// // Do nothing, continue.
+/// Ok(()) => (),
+/// }
+///
+/// match numbers.push(200, GFP_KERNEL) {
+/// Err(e) => {
+/// pr_err!("Error pushing 200: {e:?}");
+/// return Err(e.into());
+/// }
+/// // Do nothing, continue.
+/// Ok(()) => (),
+/// }
+///
+/// Ok(())
+/// }
+/// # example()?;
+/// # Ok::<(), Error>(())
+/// ```
+///
+/// An alternative to be more concise is the [`if let`] syntax:
+///
+/// ```
+/// fn example() -> Result {
+/// let mut numbers = KVec::new();
+///
+/// if let Err(e) = numbers.push(72, GFP_KERNEL) {
+/// pr_err!("Error pushing 72: {e:?}");
+/// return Err(e.into());
+/// }
+///
+/// if let Err(e) = numbers.push(108, GFP_KERNEL) {
+/// pr_err!("Error pushing 108: {e:?}");
+/// return Err(e.into());
+/// }
+///
+/// if let Err(e) = numbers.push(200, GFP_KERNEL) {
+/// pr_err!("Error pushing 200: {e:?}");
+/// return Err(e.into());
+/// }
+///
+/// Ok(())
+/// }
+/// # example()?;
+/// # Ok::<(), Error>(())
+/// ```
+///
+/// Instead of these verbose [`match`]/[`if let`], the [`?`] operator can
+/// be used to handle the [`Result`]. Using the [`?`] operator is often
+/// the best choice to handle [`Result`] in a non-verbose way as done in
+/// [`samples/rust/rust_minimal.rs`]:
+///
+/// ```
+/// fn example() -> Result {
+/// let mut numbers = KVec::new();
+///
+/// numbers.push(72, GFP_KERNEL)?;
+/// numbers.push(108, GFP_KERNEL)?;
+/// numbers.push(200, GFP_KERNEL)?;
+///
+/// Ok(())
+/// }
+/// # example()?;
+/// # Ok::<(), Error>(())
+/// ```
+///
+/// Another possibility is to call [`unwrap()`](Result::unwrap) or
+/// [`expect()`](Result::expect). However, use of these functions is
+/// *heavily discouraged* in the kernel because they trigger a Rust
+/// [`panic!`] if an error happens, which may destabilize the system or
+/// entirely break it as a result -- just like the C [`BUG()`] macro.
+/// Please see the documentation for the C macro [`BUG()`] for guidance
+/// on when to use these functions.
+///
+/// Alternatively, depending on the use case, using [`unwrap_or()`],
+/// [`unwrap_or_else()`], [`unwrap_or_default()`] or [`unwrap_unchecked()`]
+/// might be an option, as well.
+///
+/// For even more details, please see the [Rust documentation].
+///
+/// [`match`]: https://doc.rust-lang.org/reference/expressions/match-expr.html
+/// [`samples/rust/rust_minimal.rs`]: srctree/samples/rust/rust_minimal.rs
+/// [`if let`]: https://doc.rust-lang.org/reference/expressions/if-expr.html#if-let-expressions
+/// [`?`]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator
+/// [`unwrap()`]: Result::unwrap
+/// [`expect()`]: Result::expect
+/// [`BUG()`]: https://docs.kernel.org/process/deprecated.html#bug-and-bug-on
+/// [`unwrap_or()`]: Result::unwrap_or
+/// [`unwrap_or_else()`]: Result::unwrap_or_else
+/// [`unwrap_or_default()`]: Result::unwrap_or_default
+/// [`unwrap_unchecked()`]: Result::unwrap_unchecked
+/// [Rust documentation]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html
pub type Result<T = (), E = Error> = core::result::Result<T, E>;
/// Converts an integer as returned by a C kernel function to an error if it's negative, and
diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs
index c5162fdc95ff..f04b058b09b2 100644
--- a/rust/kernel/firmware.rs
+++ b/rust/kernel/firmware.rs
@@ -115,3 +115,219 @@ unsafe impl Send for Firmware {}
// SAFETY: `Firmware` only holds a pointer to a C `struct firmware`, references to which are safe to
// be used from any thread.
unsafe impl Sync for Firmware {}
+
+/// Create firmware .modinfo entries.
+///
+/// This macro is the counterpart of the C macro `MODULE_FIRMWARE()`, but instead of taking a
+/// simple string literals, which is already covered by the `firmware` field of
+/// [`crate::prelude::module!`], it allows the caller to pass a builder type, based on the
+/// [`ModInfoBuilder`], which can create the firmware modinfo strings in a more flexible way.
+///
+/// Drivers should extend the [`ModInfoBuilder`] with their own driver specific builder type.
+///
+/// The `builder` argument must be a type which implements the following function.
+///
+/// `const fn create(module_name: &'static CStr) -> ModInfoBuilder`
+///
+/// `create` should pass the `module_name` to the [`ModInfoBuilder`] and, with the help of
+/// it construct the corresponding firmware modinfo.
+///
+/// Typically, such contracts would be enforced by a trait, however traits do not (yet) support
+/// const functions.
+///
+/// # Example
+///
+/// ```
+/// # mod module_firmware_test {
+/// # use kernel::firmware;
+/// # use kernel::prelude::*;
+/// #
+/// # struct MyModule;
+/// #
+/// # impl kernel::Module for MyModule {
+/// # fn init(_module: &'static ThisModule) -> Result<Self> {
+/// # Ok(Self)
+/// # }
+/// # }
+/// #
+/// #
+/// struct Builder<const N: usize>;
+///
+/// impl<const N: usize> Builder<N> {
+/// const DIR: &'static str = "vendor/chip/";
+/// const FILES: [&'static str; 3] = [ "foo", "bar", "baz" ];
+///
+/// const fn create(module_name: &'static kernel::str::CStr) -> firmware::ModInfoBuilder<N> {
+/// let mut builder = firmware::ModInfoBuilder::new(module_name);
+///
+/// let mut i = 0;
+/// while i < Self::FILES.len() {
+/// builder = builder.new_entry()
+/// .push(Self::DIR)
+/// .push(Self::FILES[i])
+/// .push(".bin");
+///
+/// i += 1;
+/// }
+///
+/// builder
+/// }
+/// }
+///
+/// module! {
+/// type: MyModule,
+/// name: "module_firmware_test",
+/// author: "Rust for Linux",
+/// description: "module_firmware! test module",
+/// license: "GPL",
+/// }
+///
+/// kernel::module_firmware!(Builder);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! module_firmware {
+ // The argument is the builder type without the const generic, since it's deferred from within
+ // this macro. Hence, we can neither use `expr` nor `ty`.
+ ($($builder:tt)*) => {
+ const _: () = {
+ const __MODULE_FIRMWARE_PREFIX: &'static $crate::str::CStr = if cfg!(MODULE) {
+ $crate::c_str!("")
+ } else {
+ <LocalModule as $crate::ModuleMetadata>::NAME
+ };
+
+ #[link_section = ".modinfo"]
+ #[used]
+ static __MODULE_FIRMWARE: [u8; $($builder)*::create(__MODULE_FIRMWARE_PREFIX)
+ .build_length()] = $($builder)*::create(__MODULE_FIRMWARE_PREFIX).build();
+ };
+ };
+}
+
+/// Builder for firmware module info.
+///
+/// [`ModInfoBuilder`] is a helper component to flexibly compose firmware paths strings for the
+/// .modinfo section in const context.
+///
+/// Therefore the [`ModInfoBuilder`] provides the methods [`ModInfoBuilder::new_entry`] and
+/// [`ModInfoBuilder::push`], where the latter is used to push path components and the former to
+/// mark the beginning of a new path string.
+///
+/// [`ModInfoBuilder`] is meant to be used in combination with [`kernel::module_firmware!`].
+///
+/// The const generic `N` as well as the `module_name` parameter of [`ModInfoBuilder::new`] is an
+/// internal implementation detail and supplied through the above macro.
+pub struct ModInfoBuilder<const N: usize> {
+ buf: [u8; N],
+ n: usize,
+ module_name: &'static CStr,
+}
+
+impl<const N: usize> ModInfoBuilder<N> {
+ /// Create an empty builder instance.
+ pub const fn new(module_name: &'static CStr) -> Self {
+ Self {
+ buf: [0; N],
+ n: 0,
+ module_name,
+ }
+ }
+
+ const fn push_internal(mut self, bytes: &[u8]) -> Self {
+ let mut j = 0;
+
+ if N == 0 {
+ self.n += bytes.len();
+ return self;
+ }
+
+ while j < bytes.len() {
+ if self.n < N {
+ self.buf[self.n] = bytes[j];
+ }
+ self.n += 1;
+ j += 1;
+ }
+ self
+ }
+
+ /// Push an additional path component.
+ ///
+ /// Append path components to the [`ModInfoBuilder`] instance. Paths need to be separated
+ /// with [`ModInfoBuilder::new_entry`].
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use kernel::firmware::ModInfoBuilder;
+ ///
+ /// # const DIR: &str = "vendor/chip/";
+ /// # const fn no_run<const N: usize>(builder: ModInfoBuilder<N>) {
+ /// let builder = builder.new_entry()
+ /// .push(DIR)
+ /// .push("foo.bin")
+ /// .new_entry()
+ /// .push(DIR)
+ /// .push("bar.bin");
+ /// # }
+ /// ```
+ pub const fn push(self, s: &str) -> Self {
+ // Check whether there has been an initial call to `next_entry()`.
+ if N != 0 && self.n == 0 {
+ crate::build_error!("Must call next_entry() before push().");
+ }
+
+ self.push_internal(s.as_bytes())
+ }
+
+ const fn push_module_name(self) -> Self {
+ let mut this = self;
+ let module_name = this.module_name;
+
+ if !this.module_name.is_empty() {
+ this = this.push_internal(module_name.as_bytes_with_nul());
+
+ if N != 0 {
+ // Re-use the space taken by the NULL terminator and swap it with the '.' separator.
+ this.buf[this.n - 1] = b'.';
+ }
+ }
+
+ this
+ }
+
+ /// Prepare the [`ModInfoBuilder`] for the next entry.
+ ///
+ /// This method acts as a separator between module firmware path entries.
+ ///
+ /// Must be called before constructing a new entry with subsequent calls to
+ /// [`ModInfoBuilder::push`].
+ ///
+ /// See [`ModInfoBuilder::push`] for an example.
+ pub const fn new_entry(self) -> Self {
+ self.push_internal(b"\0")
+ .push_module_name()
+ .push_internal(b"firmware=")
+ }
+
+ /// Build the byte array.
+ pub const fn build(self) -> [u8; N] {
+ // Add the final NULL terminator.
+ let this = self.push_internal(b"\0");
+
+ if this.n == N {
+ this.buf
+ } else {
+ crate::build_error!("Length mismatch.");
+ }
+ }
+}
+
+impl ModInfoBuilder<0> {
+ /// Return the length of the byte array to build.
+ pub const fn build_length(self) -> usize {
+ // Compensate for the NULL terminator added by `build`.
+ self.n + 1
+ }
+}
diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs
index e03dbe14d62a..13a0e44cd1aa 100644
--- a/rust/kernel/fs/file.rs
+++ b/rust/kernel/fs/file.rs
@@ -267,7 +267,7 @@ impl LocalFile {
/// # Safety
///
/// * The caller must ensure that `ptr` points at a valid file and that the file's refcount is
- /// positive for the duration of 'a.
+ /// positive for the duration of `'a`.
/// * The caller must ensure that if there is an active call to `fdget_pos` that did not take
/// the `f_pos_lock` mutex, then that call is on the current thread.
#[inline]
@@ -341,7 +341,7 @@ impl File {
/// # Safety
///
/// * The caller must ensure that `ptr` points at a valid file and that the file's refcount is
- /// positive for the duration of 'a.
+ /// positive for the duration of `'a`.
/// * The caller must ensure that if there are active `fdget_pos` calls on this file, then they
/// took the `f_pos_lock` mutex.
#[inline]
@@ -392,6 +392,7 @@ pub struct FileDescriptorReservation {
impl FileDescriptorReservation {
/// Creates a new file descriptor reservation.
+ #[inline]
pub fn get_unused_fd_flags(flags: u32) -> Result<Self> {
// SAFETY: FFI call, there are no safety requirements on `flags`.
let fd: i32 = unsafe { bindings::get_unused_fd_flags(flags) };
@@ -405,6 +406,7 @@ impl FileDescriptorReservation {
}
/// Returns the file descriptor number that was reserved.
+ #[inline]
pub fn reserved_fd(&self) -> u32 {
self.fd
}
@@ -413,6 +415,7 @@ impl FileDescriptorReservation {
///
/// The previously reserved file descriptor is bound to `file`. This method consumes the
/// [`FileDescriptorReservation`], so it will not be usable after this call.
+ #[inline]
pub fn fd_install(self, file: ARef<File>) {
// SAFETY: `self.fd` was previously returned by `get_unused_fd_flags`. We have not yet used
// the fd, so it is still valid, and `current` still refers to the same task, as this type
@@ -433,6 +436,7 @@ impl FileDescriptorReservation {
}
impl Drop for FileDescriptorReservation {
+ #[inline]
fn drop(&mut self) {
// SAFETY: By the type invariants of this type, `self.fd` was previously returned by
// `get_unused_fd_flags`. We have not yet used the fd, so it is still valid, and `current`
diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
index e25d047f3c82..8d228c237954 100644
--- a/rust/kernel/init.rs
+++ b/rust/kernel/init.rs
@@ -1,131 +1,77 @@
-// SPDX-License-Identifier: Apache-2.0 OR MIT
+// SPDX-License-Identifier: GPL-2.0
-//! API to safely and fallibly initialize pinned `struct`s using in-place constructors.
-//!
-//! It also allows in-place initialization of big `struct`s that would otherwise produce a stack
-//! overflow.
+//! Extensions to the [`pin-init`] crate.
//!
//! Most `struct`s from the [`sync`] module need to be pinned, because they contain self-referential
//! `struct`s from C. [Pinning][pinning] is Rust's way of ensuring data does not move.
//!
-//! # Overview
+//! The [`pin-init`] crate is the way such structs are initialized on the Rust side. Please refer
+//! to its documentation to better understand how to use it. Additionally, there are many examples
+//! throughout the kernel, such as the types from the [`sync`] module. And the ones presented
+//! below.
+//!
+//! [`sync`]: crate::sync
+//! [pinning]: https://doc.rust-lang.org/std/pin/index.html
+//! [`pin-init`]: https://rust.docs.kernel.org/pin_init/
//!
-//! To initialize a `struct` with an in-place constructor you will need two things:
-//! - an in-place constructor,
-//! - a memory location that can hold your `struct` (this can be the [stack], an [`Arc<T>`],
-//! [`UniqueArc<T>`], [`KBox<T>`] or any other smart pointer that implements [`InPlaceInit`]).
+//! # [`Opaque<T>`]
//!
-//! To get an in-place constructor there are generally three options:
-//! - directly creating an in-place constructor using the [`pin_init!`] macro,
-//! - a custom function/macro returning an in-place constructor provided by someone else,
-//! - using the unsafe function [`pin_init_from_closure()`] to manually create an initializer.
+//! For the special case where initializing a field is a single FFI-function call that cannot fail,
+//! there exist the helper function [`Opaque::ffi_init`]. This function initialize a single
+//! [`Opaque<T>`] field by just delegating to the supplied closure. You can use these in
+//! combination with [`pin_init!`].
//!
-//! Aside from pinned initialization, this API also supports in-place construction without pinning,
-//! the macros/types/functions are generally named like the pinned variants without the `pin`
-//! prefix.
+//! [`Opaque<T>`]: crate::types::Opaque
+//! [`Opaque::ffi_init`]: crate::types::Opaque::ffi_init
+//! [`pin_init!`]: pin_init::pin_init
//!
//! # Examples
//!
-//! ## Using the [`pin_init!`] macro
+//! ## General Examples
//!
-//! If you want to use [`PinInit`], then you will have to annotate your `struct` with
-//! `#[`[`pin_data`]`]`. It is a macro that uses `#[pin]` as a marker for
-//! [structurally pinned fields]. After doing this, you can then create an in-place constructor via
-//! [`pin_init!`]. The syntax is almost the same as normal `struct` initializers. The difference is
-//! that you need to write `<-` instead of `:` for fields that you want to initialize in-place.
+//! ```rust,ignore
+//! # #![allow(clippy::disallowed_names)]
+//! use kernel::types::Opaque;
+//! use pin_init::pin_init_from_closure;
//!
-//! ```rust
-//! # #![expect(clippy::disallowed_names)]
-//! use kernel::sync::{new_mutex, Mutex};
-//! # use core::pin::Pin;
-//! #[pin_data]
-//! struct Foo {
-//! #[pin]
-//! a: Mutex<usize>,
-//! b: u32,
+//! // assume we have some `raw_foo` type in C:
+//! #[repr(C)]
+//! struct RawFoo([u8; 16]);
+//! extern {
+//! fn init_foo(_: *mut RawFoo);
//! }
//!
-//! let foo = pin_init!(Foo {
-//! a <- new_mutex!(42, "Foo::a"),
-//! b: 24,
-//! });
-//! ```
-//!
-//! `foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like
-//! (or just the stack) to actually initialize a `Foo`:
-//!
-//! ```rust
-//! # #![expect(clippy::disallowed_names)]
-//! # use kernel::sync::{new_mutex, Mutex};
-//! # use core::pin::Pin;
-//! # #[pin_data]
-//! # struct Foo {
-//! # #[pin]
-//! # a: Mutex<usize>,
-//! # b: u32,
-//! # }
-//! # let foo = pin_init!(Foo {
-//! # a <- new_mutex!(42, "Foo::a"),
-//! # b: 24,
-//! # });
-//! let foo: Result<Pin<KBox<Foo>>> = KBox::pin_init(foo, GFP_KERNEL);
-//! ```
-//!
-//! For more information see the [`pin_init!`] macro.
-//!
-//! ## Using a custom function/macro that returns an initializer
-//!
-//! Many types from the kernel supply a function/macro that returns an initializer, because the
-//! above method only works for types where you can access the fields.
-//!
-//! ```rust
-//! # use kernel::sync::{new_mutex, Arc, Mutex};
-//! let mtx: Result<Arc<Mutex<usize>>> =
-//! Arc::pin_init(new_mutex!(42, "example::mtx"), GFP_KERNEL);
-//! ```
-//!
-//! To declare an init macro/function you just return an [`impl PinInit<T, E>`]:
-//!
-//! ```rust
-//! # use kernel::{sync::Mutex, new_mutex, init::PinInit, try_pin_init};
//! #[pin_data]
-//! struct DriverData {
+//! struct Foo {
//! #[pin]
-//! status: Mutex<i32>,
-//! buffer: KBox<[u8; 1_000_000]>,
+//! raw: Opaque<RawFoo>,
//! }
//!
-//! impl DriverData {
-//! fn new() -> impl PinInit<Self, Error> {
-//! try_pin_init!(Self {
-//! status <- new_mutex!(0, "DriverData::status"),
-//! buffer: KBox::init(kernel::init::zeroed(), GFP_KERNEL)?,
-//! })
+//! impl Foo {
+//! fn setup(self: Pin<&mut Self>) {
+//! pr_info!("Setting up foo\n");
//! }
//! }
-//! ```
//!
-//! ## Manual creation of an initializer
-//!
-//! Often when working with primitives the previous approaches are not sufficient. That is where
-//! [`pin_init_from_closure()`] comes in. This `unsafe` function allows you to create a
-//! [`impl PinInit<T, E>`] directly from a closure. Of course you have to ensure that the closure
-//! actually does the initialization in the correct way. Here are the things to look out for
-//! (we are calling the parameter to the closure `slot`):
-//! - when the closure returns `Ok(())`, then it has completed the initialization successfully, so
-//! `slot` now contains a valid bit pattern for the type `T`,
-//! - when the closure returns `Err(e)`, then the caller may deallocate the memory at `slot`, so
-//! you need to take care to clean up anything if your initialization fails mid-way,
-//! - you may assume that `slot` will stay pinned even after the closure returns until `drop` of
-//! `slot` gets called.
+//! let foo = pin_init!(Foo {
+//! raw <- unsafe {
+//! Opaque::ffi_init(|s| {
+//! // note that this cannot fail.
+//! init_foo(s);
+//! })
+//! },
+//! }).pin_chain(|foo| {
+//! foo.setup();
+//! Ok(())
+//! });
+//! ```
//!
-//! ```rust
-//! # #![expect(unreachable_pub, clippy::disallowed_names)]
-//! use kernel::{init, types::Opaque};
+//! ```rust,ignore
+//! # #![allow(unreachable_pub, clippy::disallowed_names)]
+//! use kernel::{prelude::*, types::Opaque};
//! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};
//! # mod bindings {
-//! # #![expect(non_camel_case_types)]
-//! # #![expect(clippy::missing_safety_doc)]
+//! # #![allow(non_camel_case_types)]
//! # pub struct foo;
//! # pub unsafe fn init_foo(_ptr: *mut foo) {}
//! # pub unsafe fn destroy_foo(_ptr: *mut foo) {}
@@ -133,7 +79,7 @@
//! # }
//! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround.
//! # trait FromErrno {
-//! # fn from_errno(errno: kernel::ffi::c_int) -> Error {
+//! # fn from_errno(errno: core::ffi::c_int) -> Error {
//! # // Dummy error that can be constructed outside the `kernel` crate.
//! # Error::from(core::fmt::Error)
//! # }
@@ -157,7 +103,7 @@
//! // enabled `foo`,
//! // - when it returns `Err(e)`, then it has cleaned up before
//! unsafe {
-//! init::pin_init_from_closure(move |slot: *mut Self| {
+//! pin_init::pin_init_from_closure(move |slot: *mut Self| {
//! // `slot` contains uninit memory, avoid creating a reference.
//! let foo = addr_of_mut!((*slot).foo);
//!
@@ -187,401 +133,114 @@
//! }
//! }
//! ```
-//!
-//! For the special case where initializing a field is a single FFI-function call that cannot fail,
-//! there exist the helper function [`Opaque::ffi_init`]. This function initialize a single
-//! [`Opaque`] field by just delegating to the supplied closure. You can use these in combination
-//! with [`pin_init!`].
-//!
-//! For more information on how to use [`pin_init_from_closure()`], take a look at the uses inside
-//! the `kernel` crate. The [`sync`] module is a good starting point.
-//!
-//! [`sync`]: kernel::sync
-//! [pinning]: https://doc.rust-lang.org/std/pin/index.html
-//! [structurally pinned fields]:
-//! https://doc.rust-lang.org/std/pin/index.html#pinning-is-structural-for-field
-//! [stack]: crate::stack_pin_init
-//! [`Arc<T>`]: crate::sync::Arc
-//! [`impl PinInit<Foo>`]: PinInit
-//! [`impl PinInit<T, E>`]: PinInit
-//! [`impl Init<T, E>`]: Init
-//! [`Opaque`]: kernel::types::Opaque
-//! [`Opaque::ffi_init`]: kernel::types::Opaque::ffi_init
-//! [`pin_data`]: ::macros::pin_data
-//! [`pin_init!`]: crate::pin_init!
use crate::{
- alloc::{AllocError, Flags, KBox},
+ alloc::{AllocError, Flags},
error::{self, Error},
- sync::Arc,
- sync::UniqueArc,
- types::{Opaque, ScopeGuard},
-};
-use core::{
- cell::UnsafeCell,
- convert::Infallible,
- marker::PhantomData,
- mem::MaybeUninit,
- num::*,
- pin::Pin,
- ptr::{self, NonNull},
};
+use pin_init::{init_from_closure, pin_init_from_closure, Init, PinInit};
-#[doc(hidden)]
-pub mod __internal;
-#[doc(hidden)]
-pub mod macros;
+/// Smart pointer that can initialize memory in-place.
+pub trait InPlaceInit<T>: Sized {
+ /// Pinned version of `Self`.
+ ///
+ /// If a type already implicitly pins its pointee, `Pin<Self>` is unnecessary. In this case use
+ /// `Self`, otherwise just use `Pin<Self>`.
+ type PinnedSelf;
-/// Initialize and pin a type directly on the stack.
-///
-/// # Examples
-///
-/// ```rust
-/// # #![expect(clippy::disallowed_names)]
-/// # use kernel::{init, macros::pin_data, pin_init, stack_pin_init, init::*, sync::Mutex, new_mutex};
-/// # use core::pin::Pin;
-/// #[pin_data]
-/// struct Foo {
-/// #[pin]
-/// a: Mutex<usize>,
-/// b: Bar,
-/// }
-///
-/// #[pin_data]
-/// struct Bar {
-/// x: u32,
-/// }
-///
-/// stack_pin_init!(let foo = pin_init!(Foo {
-/// a <- new_mutex!(42),
-/// b: Bar {
-/// x: 64,
-/// },
-/// }));
-/// let foo: Pin<&mut Foo> = foo;
-/// pr_info!("a: {}\n", &*foo.a.lock());
-/// ```
-///
-/// # Syntax
-///
-/// A normal `let` binding with optional type annotation. The expression is expected to implement
-/// [`PinInit`]/[`Init`] with the error type [`Infallible`]. If you want to use a different error
-/// type, then use [`stack_try_pin_init!`].
-///
-/// [`stack_try_pin_init!`]: crate::stack_try_pin_init!
-#[macro_export]
-macro_rules! stack_pin_init {
- (let $var:ident $(: $t:ty)? = $val:expr) => {
- let val = $val;
- let mut $var = ::core::pin::pin!($crate::init::__internal::StackInit$(::<$t>)?::uninit());
- let mut $var = match $crate::init::__internal::StackInit::init($var, val) {
- Ok(res) => res,
- Err(x) => {
- let x: ::core::convert::Infallible = x;
- match x {}
- }
+ /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
+ /// type.
+ ///
+ /// If `T: !Unpin` it will not be able to move afterwards.
+ fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
+ where
+ E: From<AllocError>;
+
+ /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
+ /// type.
+ ///
+ /// If `T: !Unpin` it will not be able to move afterwards.
+ fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf>
+ where
+ Error: From<E>,
+ {
+ // SAFETY: We delegate to `init` and only change the error type.
+ let init = unsafe {
+ pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
};
- };
-}
+ Self::try_pin_init(init, flags)
+ }
-/// Initialize and pin a type directly on the stack.
-///
-/// # Examples
-///
-/// ```rust,ignore
-/// # #![expect(clippy::disallowed_names)]
-/// # use kernel::{
-/// # init,
-/// # pin_init,
-/// # stack_try_pin_init,
-/// # init::*,
-/// # sync::Mutex,
-/// # new_mutex,
-/// # alloc::AllocError,
-/// # };
-/// # use macros::pin_data;
-/// # use core::pin::Pin;
-/// #[pin_data]
-/// struct Foo {
-/// #[pin]
-/// a: Mutex<usize>,
-/// b: KBox<Bar>,
-/// }
-///
-/// struct Bar {
-/// x: u32,
-/// }
-///
-/// stack_try_pin_init!(let foo: Result<Pin<&mut Foo>, AllocError> = pin_init!(Foo {
-/// a <- new_mutex!(42),
-/// b: KBox::new(Bar {
-/// x: 64,
-/// }, GFP_KERNEL)?,
-/// }));
-/// let foo = foo.unwrap();
-/// pr_info!("a: {}\n", &*foo.a.lock());
-/// ```
-///
-/// ```rust,ignore
-/// # #![expect(clippy::disallowed_names)]
-/// # use kernel::{
-/// # init,
-/// # pin_init,
-/// # stack_try_pin_init,
-/// # init::*,
-/// # sync::Mutex,
-/// # new_mutex,
-/// # alloc::AllocError,
-/// # };
-/// # use macros::pin_data;
-/// # use core::pin::Pin;
-/// #[pin_data]
-/// struct Foo {
-/// #[pin]
-/// a: Mutex<usize>,
-/// b: KBox<Bar>,
-/// }
-///
-/// struct Bar {
-/// x: u32,
-/// }
-///
-/// stack_try_pin_init!(let foo: Pin<&mut Foo> =? pin_init!(Foo {
-/// a <- new_mutex!(42),
-/// b: KBox::new(Bar {
-/// x: 64,
-/// }, GFP_KERNEL)?,
-/// }));
-/// pr_info!("a: {}\n", &*foo.a.lock());
-/// # Ok::<_, AllocError>(())
-/// ```
-///
-/// # Syntax
-///
-/// A normal `let` binding with optional type annotation. The expression is expected to implement
-/// [`PinInit`]/[`Init`]. This macro assigns a result to the given variable, adding a `?` after the
-/// `=` will propagate this error.
-#[macro_export]
-macro_rules! stack_try_pin_init {
- (let $var:ident $(: $t:ty)? = $val:expr) => {
- let val = $val;
- let mut $var = ::core::pin::pin!($crate::init::__internal::StackInit$(::<$t>)?::uninit());
- let mut $var = $crate::init::__internal::StackInit::init($var, val);
- };
- (let $var:ident $(: $t:ty)? =? $val:expr) => {
- let val = $val;
- let mut $var = ::core::pin::pin!($crate::init::__internal::StackInit$(::<$t>)?::uninit());
- let mut $var = $crate::init::__internal::StackInit::init($var, val)?;
- };
+ /// Use the given initializer to in-place initialize a `T`.
+ fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
+ where
+ E: From<AllocError>;
+
+ /// Use the given initializer to in-place initialize a `T`.
+ fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
+ where
+ Error: From<E>,
+ {
+ // SAFETY: We delegate to `init` and only change the error type.
+ let init = unsafe {
+ init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
+ };
+ Self::try_init(init, flags)
+ }
}
-/// Construct an in-place, pinned initializer for `struct`s.
-///
-/// This macro defaults the error to [`Infallible`]. If you need [`Error`], then use
-/// [`try_pin_init!`].
-///
-/// The syntax is almost identical to that of a normal `struct` initializer:
-///
-/// ```rust
-/// # use kernel::{init, pin_init, macros::pin_data, init::*};
-/// # use core::pin::Pin;
-/// #[pin_data]
-/// struct Foo {
-/// a: usize,
-/// b: Bar,
-/// }
-///
-/// #[pin_data]
-/// struct Bar {
-/// x: u32,
-/// }
-///
-/// # fn demo() -> impl PinInit<Foo> {
-/// let a = 42;
-///
-/// let initializer = pin_init!(Foo {
-/// a,
-/// b: Bar {
-/// x: 64,
-/// },
-/// });
-/// # initializer }
-/// # KBox::pin_init(demo(), GFP_KERNEL).unwrap();
-/// ```
-///
-/// Arbitrary Rust expressions can be used to set the value of a variable.
-///
-/// The fields are initialized in the order that they appear in the initializer. So it is possible
-/// to read already initialized fields using raw pointers.
-///
-/// IMPORTANT: You are not allowed to create references to fields of the struct inside of the
-/// initializer.
-///
-/// # Init-functions
-///
-/// When working with this API it is often desired to let others construct your types without
-/// giving access to all fields. This is where you would normally write a plain function `new`
-/// that would return a new instance of your type. With this API that is also possible.
-/// However, there are a few extra things to keep in mind.
-///
-/// To create an initializer function, simply declare it like this:
-///
-/// ```rust
-/// # use kernel::{init, pin_init, init::*};
-/// # use core::pin::Pin;
-/// # #[pin_data]
-/// # struct Foo {
-/// # a: usize,
-/// # b: Bar,
-/// # }
-/// # #[pin_data]
-/// # struct Bar {
-/// # x: u32,
-/// # }
-/// impl Foo {
-/// fn new() -> impl PinInit<Self> {
-/// pin_init!(Self {
-/// a: 42,
-/// b: Bar {
-/// x: 64,
-/// },
-/// })
-/// }
-/// }
-/// ```
+/// Construct an in-place fallible initializer for `struct`s.
///
-/// Users of `Foo` can now create it like this:
+/// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
+/// [`init!`].
///
-/// ```rust
-/// # #![expect(clippy::disallowed_names)]
-/// # use kernel::{init, pin_init, macros::pin_data, init::*};
-/// # use core::pin::Pin;
-/// # #[pin_data]
-/// # struct Foo {
-/// # a: usize,
-/// # b: Bar,
-/// # }
-/// # #[pin_data]
-/// # struct Bar {
-/// # x: u32,
-/// # }
-/// # impl Foo {
-/// # fn new() -> impl PinInit<Self> {
-/// # pin_init!(Self {
-/// # a: 42,
-/// # b: Bar {
-/// # x: 64,
-/// # },
-/// # })
-/// # }
-/// # }
-/// let foo = KBox::pin_init(Foo::new(), GFP_KERNEL);
-/// ```
+/// The syntax is identical to [`try_pin_init!`]. If you want to specify a custom error,
+/// append `? $type` after the `struct` initializer.
+/// The safety caveats from [`try_pin_init!`] also apply:
+/// - `unsafe` code must guarantee either full initialization or return an error and allow
+/// deallocation of the memory.
+/// - the fields are initialized in the order given in the initializer.
+/// - no references to fields are allowed to be created inside of the initializer.
///
-/// They can also easily embed it into their own `struct`s:
+/// # Examples
///
/// ```rust
-/// # use kernel::{init, pin_init, macros::pin_data, init::*};
-/// # use core::pin::Pin;
-/// # #[pin_data]
-/// # struct Foo {
-/// # a: usize,
-/// # b: Bar,
-/// # }
-/// # #[pin_data]
-/// # struct Bar {
-/// # x: u32,
-/// # }
-/// # impl Foo {
-/// # fn new() -> impl PinInit<Self> {
-/// # pin_init!(Self {
-/// # a: 42,
-/// # b: Bar {
-/// # x: 64,
-/// # },
-/// # })
-/// # }
-/// # }
-/// #[pin_data]
-/// struct FooContainer {
-/// #[pin]
-/// foo1: Foo,
-/// #[pin]
-/// foo2: Foo,
-/// other: u32,
+/// use kernel::error::Error;
+/// use pin_init::zeroed;
+/// struct BigBuf {
+/// big: KBox<[u8; 1024 * 1024 * 1024]>,
+/// small: [u8; 1024 * 1024],
/// }
///
-/// impl FooContainer {
-/// fn new(other: u32) -> impl PinInit<Self> {
-/// pin_init!(Self {
-/// foo1 <- Foo::new(),
-/// foo2 <- Foo::new(),
-/// other,
-/// })
+/// impl BigBuf {
+/// fn new() -> impl Init<Self, Error> {
+/// try_init!(Self {
+/// big: KBox::init(zeroed(), GFP_KERNEL)?,
+/// small: [0; 1024 * 1024],
+/// }? Error)
/// }
/// }
/// ```
///
-/// Here we see that when using `pin_init!` with `PinInit`, one needs to write `<-` instead of `:`.
-/// This signifies that the given field is initialized in-place. As with `struct` initializers, just
-/// writing the field (in this case `other`) without `:` or `<-` means `other: other,`.
-///
-/// # Syntax
-///
-/// As already mentioned in the examples above, inside of `pin_init!` a `struct` initializer with
-/// the following modifications is expected:
-/// - Fields that you want to initialize in-place have to use `<-` instead of `:`.
-/// - In front of the initializer you can write `&this in` to have access to a [`NonNull<Self>`]
-/// pointer named `this` inside of the initializer.
-/// - Using struct update syntax one can place `..Zeroable::zeroed()` at the very end of the
-/// struct, this initializes every field with 0 and then runs all initializers specified in the
-/// body. This can only be done if [`Zeroable`] is implemented for the struct.
-///
-/// For instance:
-///
-/// ```rust
-/// # use kernel::{macros::{Zeroable, pin_data}, pin_init};
-/// # use core::{ptr::addr_of_mut, marker::PhantomPinned};
-/// #[pin_data]
-/// #[derive(Zeroable)]
-/// struct Buf {
-/// // `ptr` points into `buf`.
-/// ptr: *mut u8,
-/// buf: [u8; 64],
-/// #[pin]
-/// pin: PhantomPinned,
-/// }
-/// pin_init!(&this in Buf {
-/// buf: [0; 64],
-/// // SAFETY: TODO.
-/// ptr: unsafe { addr_of_mut!((*this.as_ptr()).buf).cast() },
-/// pin: PhantomPinned,
-/// });
-/// pin_init!(Buf {
-/// buf: [1; 64],
-/// ..Zeroable::zeroed()
-/// });
-/// ```
-///
-/// [`try_pin_init!`]: kernel::try_pin_init
-/// [`NonNull<Self>`]: core::ptr::NonNull
-// For a detailed example of how this macro works, see the module documentation of the hidden
-// module `__internal` inside of `init/__internal.rs`.
+/// [`Infallible`]: core::convert::Infallible
+/// [`init!`]: pin_init::init
+/// [`try_pin_init!`]: crate::try_pin_init!
+/// [`Error`]: crate::error::Error
#[macro_export]
-macro_rules! pin_init {
+macro_rules! try_init {
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
$($fields:tt)*
}) => {
- $crate::__init_internal!(
- @this($($this)?),
- @typ($t $(::<$($generics),*>)?),
- @fields($($fields)*),
- @error(::core::convert::Infallible),
- @data(PinData, use_data),
- @has_data(HasPinData, __pin_data),
- @construct_closure(pin_init_from_closure),
- @munch_fields($($fields)*),
- )
+ ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+ $($fields)*
+ }? $crate::error::Error)
+ };
+ ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
+ $($fields:tt)*
+ }? $err:ty) => {
+ ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+ $($fields)*
+ }? $err)
};
}
@@ -603,7 +262,9 @@ macro_rules! pin_init {
/// # Examples
///
/// ```rust
-/// use kernel::{init::{self, PinInit}, error::Error};
+/// # #![feature(new_uninit)]
+/// use kernel::error::Error;
+/// use pin_init::zeroed;
/// #[pin_data]
/// struct BigBuf {
/// big: KBox<[u8; 1024 * 1024 * 1024]>,
@@ -614,843 +275,31 @@ macro_rules! pin_init {
/// impl BigBuf {
/// fn new() -> impl PinInit<Self, Error> {
/// try_pin_init!(Self {
-/// big: KBox::init(init::zeroed(), GFP_KERNEL)?,
+/// big: KBox::init(zeroed(), GFP_KERNEL)?,
/// small: [0; 1024 * 1024],
/// ptr: core::ptr::null_mut(),
/// }? Error)
/// }
/// }
/// ```
-// For a detailed example of how this macro works, see the module documentation of the hidden
-// module `__internal` inside of `init/__internal.rs`.
-#[macro_export]
-macro_rules! try_pin_init {
- ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
- $($fields:tt)*
- }) => {
- $crate::__init_internal!(
- @this($($this)?),
- @typ($t $(::<$($generics),*>)? ),
- @fields($($fields)*),
- @error($crate::error::Error),
- @data(PinData, use_data),
- @has_data(HasPinData, __pin_data),
- @construct_closure(pin_init_from_closure),
- @munch_fields($($fields)*),
- )
- };
- ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
- $($fields:tt)*
- }? $err:ty) => {
- $crate::__init_internal!(
- @this($($this)?),
- @typ($t $(::<$($generics),*>)? ),
- @fields($($fields)*),
- @error($err),
- @data(PinData, use_data),
- @has_data(HasPinData, __pin_data),
- @construct_closure(pin_init_from_closure),
- @munch_fields($($fields)*),
- )
- };
-}
-
-/// Construct an in-place initializer for `struct`s.
-///
-/// This macro defaults the error to [`Infallible`]. If you need [`Error`], then use
-/// [`try_init!`].
-///
-/// The syntax is identical to [`pin_init!`] and its safety caveats also apply:
-/// - `unsafe` code must guarantee either full initialization or return an error and allow
-/// deallocation of the memory.
-/// - the fields are initialized in the order given in the initializer.
-/// - no references to fields are allowed to be created inside of the initializer.
///
-/// This initializer is for initializing data in-place that might later be moved. If you want to
-/// pin-initialize, use [`pin_init!`].
-///
-/// [`try_init!`]: crate::try_init!
-// For a detailed example of how this macro works, see the module documentation of the hidden
-// module `__internal` inside of `init/__internal.rs`.
+/// [`Infallible`]: core::convert::Infallible
+/// [`pin_init!`]: pin_init::pin_init
+/// [`Error`]: crate::error::Error
#[macro_export]
-macro_rules! init {
- ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
- $($fields:tt)*
- }) => {
- $crate::__init_internal!(
- @this($($this)?),
- @typ($t $(::<$($generics),*>)?),
- @fields($($fields)*),
- @error(::core::convert::Infallible),
- @data(InitData, /*no use_data*/),
- @has_data(HasInitData, __init_data),
- @construct_closure(init_from_closure),
- @munch_fields($($fields)*),
- )
- }
-}
-
-/// Construct an in-place fallible initializer for `struct`s.
-///
-/// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
-/// [`init!`].
-///
-/// The syntax is identical to [`try_pin_init!`]. If you want to specify a custom error,
-/// append `? $type` after the `struct` initializer.
-/// The safety caveats from [`try_pin_init!`] also apply:
-/// - `unsafe` code must guarantee either full initialization or return an error and allow
-/// deallocation of the memory.
-/// - the fields are initialized in the order given in the initializer.
-/// - no references to fields are allowed to be created inside of the initializer.
-///
-/// # Examples
-///
-/// ```rust
-/// use kernel::{alloc::KBox, init::{PinInit, zeroed}, error::Error};
-/// struct BigBuf {
-/// big: KBox<[u8; 1024 * 1024 * 1024]>,
-/// small: [u8; 1024 * 1024],
-/// }
-///
-/// impl BigBuf {
-/// fn new() -> impl Init<Self, Error> {
-/// try_init!(Self {
-/// big: KBox::init(zeroed(), GFP_KERNEL)?,
-/// small: [0; 1024 * 1024],
-/// }? Error)
-/// }
-/// }
-/// ```
-// For a detailed example of how this macro works, see the module documentation of the hidden
-// module `__internal` inside of `init/__internal.rs`.
-#[macro_export]
-macro_rules! try_init {
+macro_rules! try_pin_init {
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
$($fields:tt)*
}) => {
- $crate::__init_internal!(
- @this($($this)?),
- @typ($t $(::<$($generics),*>)?),
- @fields($($fields)*),
- @error($crate::error::Error),
- @data(InitData, /*no use_data*/),
- @has_data(HasInitData, __init_data),
- @construct_closure(init_from_closure),
- @munch_fields($($fields)*),
- )
+ ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+ $($fields)*
+ }? $crate::error::Error)
};
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
$($fields:tt)*
}? $err:ty) => {
- $crate::__init_internal!(
- @this($($this)?),
- @typ($t $(::<$($generics),*>)?),
- @fields($($fields)*),
- @error($err),
- @data(InitData, /*no use_data*/),
- @has_data(HasInitData, __init_data),
- @construct_closure(init_from_closure),
- @munch_fields($($fields)*),
- )
+ ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+ $($fields)*
+ }? $err)
};
}
-
-/// Asserts that a field on a struct using `#[pin_data]` is marked with `#[pin]` ie. that it is
-/// structurally pinned.
-///
-/// # Example
-///
-/// This will succeed:
-/// ```
-/// use kernel::assert_pinned;
-/// #[pin_data]
-/// struct MyStruct {
-/// #[pin]
-/// some_field: u64,
-/// }
-///
-/// assert_pinned!(MyStruct, some_field, u64);
-/// ```
-///
-/// This will fail:
-// TODO: replace with `compile_fail` when supported.
-/// ```ignore
-/// use kernel::assert_pinned;
-/// #[pin_data]
-/// struct MyStruct {
-/// some_field: u64,
-/// }
-///
-/// assert_pinned!(MyStruct, some_field, u64);
-/// ```
-///
-/// Some uses of the macro may trigger the `can't use generic parameters from outer item` error. To
-/// work around this, you may pass the `inline` parameter to the macro. The `inline` parameter can
-/// only be used when the macro is invoked from a function body.
-/// ```
-/// use kernel::assert_pinned;
-/// #[pin_data]
-/// struct Foo<T> {
-/// #[pin]
-/// elem: T,
-/// }
-///
-/// impl<T> Foo<T> {
-/// fn project(self: Pin<&mut Self>) -> Pin<&mut T> {
-/// assert_pinned!(Foo<T>, elem, T, inline);
-///
-/// // SAFETY: The field is structurally pinned.
-/// unsafe { self.map_unchecked_mut(|me| &mut me.elem) }
-/// }
-/// }
-/// ```
-#[macro_export]
-macro_rules! assert_pinned {
- ($ty:ty, $field:ident, $field_ty:ty, inline) => {
- let _ = move |ptr: *mut $field_ty| {
- // SAFETY: This code is unreachable.
- let data = unsafe { <$ty as $crate::init::__internal::HasPinData>::__pin_data() };
- let init = $crate::init::__internal::AlwaysFail::<$field_ty>::new();
- // SAFETY: This code is unreachable.
- unsafe { data.$field(ptr, init) }.ok();
- };
- };
-
- ($ty:ty, $field:ident, $field_ty:ty) => {
- const _: () = {
- $crate::assert_pinned!($ty, $field, $field_ty, inline);
- };
- };
-}
-
-/// A pin-initializer for the type `T`.
-///
-/// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
-/// be [`KBox<T>`], [`Arc<T>`], [`UniqueArc<T>`] or even the stack (see [`stack_pin_init!`]). Use
-/// the [`InPlaceInit::pin_init`] function of a smart pointer like [`Arc<T>`] on this.
-///
-/// Also see the [module description](self).
-///
-/// # Safety
-///
-/// When implementing this trait you will need to take great care. Also there are probably very few
-/// cases where a manual implementation is necessary. Use [`pin_init_from_closure`] where possible.
-///
-/// The [`PinInit::__pinned_init`] function:
-/// - returns `Ok(())` if it initialized every field of `slot`,
-/// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
-/// - `slot` can be deallocated without UB occurring,
-/// - `slot` does not need to be dropped,
-/// - `slot` is not partially initialized.
-/// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
-///
-/// [`Arc<T>`]: crate::sync::Arc
-/// [`Arc::pin_init`]: crate::sync::Arc::pin_init
-#[must_use = "An initializer must be used in order to create its value."]
-pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
- /// Initializes `slot`.
- ///
- /// # Safety
- ///
- /// - `slot` is a valid pointer to uninitialized memory.
- /// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
- /// deallocate.
- /// - `slot` will not move until it is dropped, i.e. it will be pinned.
- unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E>;
-
- /// First initializes the value using `self` then calls the function `f` with the initialized
- /// value.
- ///
- /// If `f` returns an error the value is dropped and the initializer will forward the error.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # #![expect(clippy::disallowed_names)]
- /// use kernel::{types::Opaque, init::pin_init_from_closure};
- /// #[repr(C)]
- /// struct RawFoo([u8; 16]);
- /// extern "C" {
- /// fn init_foo(_: *mut RawFoo);
- /// }
- ///
- /// #[pin_data]
- /// struct Foo {
- /// #[pin]
- /// raw: Opaque<RawFoo>,
- /// }
- ///
- /// impl Foo {
- /// fn setup(self: Pin<&mut Self>) {
- /// pr_info!("Setting up foo\n");
- /// }
- /// }
- ///
- /// let foo = pin_init!(Foo {
- /// // SAFETY: TODO.
- /// raw <- unsafe {
- /// Opaque::ffi_init(|s| {
- /// init_foo(s);
- /// })
- /// },
- /// }).pin_chain(|foo| {
- /// foo.setup();
- /// Ok(())
- /// });
- /// ```
- fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
- where
- F: FnOnce(Pin<&mut T>) -> Result<(), E>,
- {
- ChainPinInit(self, f, PhantomData)
- }
-}
-
-/// An initializer returned by [`PinInit::pin_chain`].
-pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, KBox<T>)>);
-
-// SAFETY: The `__pinned_init` function is implemented such that it
-// - returns `Ok(())` on successful initialization,
-// - returns `Err(err)` on error and in this case `slot` will be dropped.
-// - considers `slot` pinned.
-unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainPinInit<I, F, T, E>
-where
- I: PinInit<T, E>,
- F: FnOnce(Pin<&mut T>) -> Result<(), E>,
-{
- unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
- // SAFETY: All requirements fulfilled since this function is `__pinned_init`.
- unsafe { self.0.__pinned_init(slot)? };
- // SAFETY: The above call initialized `slot` and we still have unique access.
- let val = unsafe { &mut *slot };
- // SAFETY: `slot` is considered pinned.
- let val = unsafe { Pin::new_unchecked(val) };
- // SAFETY: `slot` was initialized above.
- (self.1)(val).inspect_err(|_| unsafe { core::ptr::drop_in_place(slot) })
- }
-}
-
-/// An initializer for `T`.
-///
-/// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
-/// be [`KBox<T>`], [`Arc<T>`], [`UniqueArc<T>`] or even the stack (see [`stack_pin_init!`]). Use
-/// the [`InPlaceInit::init`] function of a smart pointer like [`Arc<T>`] on this. Because
-/// [`PinInit<T, E>`] is a super trait, you can use every function that takes it as well.
-///
-/// Also see the [module description](self).
-///
-/// # Safety
-///
-/// When implementing this trait you will need to take great care. Also there are probably very few
-/// cases where a manual implementation is necessary. Use [`init_from_closure`] where possible.
-///
-/// The [`Init::__init`] function:
-/// - returns `Ok(())` if it initialized every field of `slot`,
-/// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
-/// - `slot` can be deallocated without UB occurring,
-/// - `slot` does not need to be dropped,
-/// - `slot` is not partially initialized.
-/// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
-///
-/// The `__pinned_init` function from the supertrait [`PinInit`] needs to execute the exact same
-/// code as `__init`.
-///
-/// Contrary to its supertype [`PinInit<T, E>`] the caller is allowed to
-/// move the pointee after initialization.
-///
-/// [`Arc<T>`]: crate::sync::Arc
-#[must_use = "An initializer must be used in order to create its value."]
-pub unsafe trait Init<T: ?Sized, E = Infallible>: PinInit<T, E> {
- /// Initializes `slot`.
- ///
- /// # Safety
- ///
- /// - `slot` is a valid pointer to uninitialized memory.
- /// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
- /// deallocate.
- unsafe fn __init(self, slot: *mut T) -> Result<(), E>;
-
- /// First initializes the value using `self` then calls the function `f` with the initialized
- /// value.
- ///
- /// If `f` returns an error the value is dropped and the initializer will forward the error.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # #![expect(clippy::disallowed_names)]
- /// use kernel::{types::Opaque, init::{self, init_from_closure}};
- /// struct Foo {
- /// buf: [u8; 1_000_000],
- /// }
- ///
- /// impl Foo {
- /// fn setup(&mut self) {
- /// pr_info!("Setting up foo\n");
- /// }
- /// }
- ///
- /// let foo = init!(Foo {
- /// buf <- init::zeroed()
- /// }).chain(|foo| {
- /// foo.setup();
- /// Ok(())
- /// });
- /// ```
- fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
- where
- F: FnOnce(&mut T) -> Result<(), E>,
- {
- ChainInit(self, f, PhantomData)
- }
-}
-
-/// An initializer returned by [`Init::chain`].
-pub struct ChainInit<I, F, T: ?Sized, E>(I, F, __internal::Invariant<(E, KBox<T>)>);
-
-// SAFETY: The `__init` function is implemented such that it
-// - returns `Ok(())` on successful initialization,
-// - returns `Err(err)` on error and in this case `slot` will be dropped.
-unsafe impl<T: ?Sized, E, I, F> Init<T, E> for ChainInit<I, F, T, E>
-where
- I: Init<T, E>,
- F: FnOnce(&mut T) -> Result<(), E>,
-{
- unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
- // SAFETY: All requirements fulfilled since this function is `__init`.
- unsafe { self.0.__pinned_init(slot)? };
- // SAFETY: The above call initialized `slot` and we still have unique access.
- (self.1)(unsafe { &mut *slot }).inspect_err(|_|
- // SAFETY: `slot` was initialized above.
- unsafe { core::ptr::drop_in_place(slot) })
- }
-}
-
-// SAFETY: `__pinned_init` behaves exactly the same as `__init`.
-unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainInit<I, F, T, E>
-where
- I: Init<T, E>,
- F: FnOnce(&mut T) -> Result<(), E>,
-{
- unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
- // SAFETY: `__init` has less strict requirements compared to `__pinned_init`.
- unsafe { self.__init(slot) }
- }
-}
-
-/// Creates a new [`PinInit<T, E>`] from the given closure.
-///
-/// # Safety
-///
-/// The closure:
-/// - returns `Ok(())` if it initialized every field of `slot`,
-/// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
-/// - `slot` can be deallocated without UB occurring,
-/// - `slot` does not need to be dropped,
-/// - `slot` is not partially initialized.
-/// - may assume that the `slot` does not move if `T: !Unpin`,
-/// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
-#[inline]
-pub const unsafe fn pin_init_from_closure<T: ?Sized, E>(
- f: impl FnOnce(*mut T) -> Result<(), E>,
-) -> impl PinInit<T, E> {
- __internal::InitClosure(f, PhantomData)
-}
-
-/// Creates a new [`Init<T, E>`] from the given closure.
-///
-/// # Safety
-///
-/// The closure:
-/// - returns `Ok(())` if it initialized every field of `slot`,
-/// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means:
-/// - `slot` can be deallocated without UB occurring,
-/// - `slot` does not need to be dropped,
-/// - `slot` is not partially initialized.
-/// - the `slot` may move after initialization.
-/// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`.
-#[inline]
-pub const unsafe fn init_from_closure<T: ?Sized, E>(
- f: impl FnOnce(*mut T) -> Result<(), E>,
-) -> impl Init<T, E> {
- __internal::InitClosure(f, PhantomData)
-}
-
-/// An initializer that leaves the memory uninitialized.
-///
-/// The initializer is a no-op. The `slot` memory is not changed.
-#[inline]
-pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
- // SAFETY: The memory is allowed to be uninitialized.
- unsafe { init_from_closure(|_| Ok(())) }
-}
-
-/// Initializes an array by initializing each element via the provided initializer.
-///
-/// # Examples
-///
-/// ```rust
-/// use kernel::{alloc::KBox, error::Error, init::init_array_from_fn};
-/// let array: KBox<[usize; 1_000]> =
-/// KBox::init::<Error>(init_array_from_fn(|i| i), GFP_KERNEL)?;
-/// assert_eq!(array.len(), 1_000);
-/// # Ok::<(), Error>(())
-/// ```
-pub fn init_array_from_fn<I, const N: usize, T, E>(
- mut make_init: impl FnMut(usize) -> I,
-) -> impl Init<[T; N], E>
-where
- I: Init<T, E>,
-{
- let init = move |slot: *mut [T; N]| {
- let slot = slot.cast::<T>();
- // Counts the number of initialized elements and when dropped drops that many elements from
- // `slot`.
- let mut init_count = ScopeGuard::new_with_data(0, |i| {
- // We now free every element that has been initialized before.
- // SAFETY: The loop initialized exactly the values from 0..i and since we
- // return `Err` below, the caller will consider the memory at `slot` as
- // uninitialized.
- unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
- });
- for i in 0..N {
- let init = make_init(i);
- // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
- let ptr = unsafe { slot.add(i) };
- // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
- // requirements.
- unsafe { init.__init(ptr) }?;
- *init_count += 1;
- }
- init_count.dismiss();
- Ok(())
- };
- // SAFETY: The initializer above initializes every element of the array. On failure it drops
- // any initialized elements and returns `Err`.
- unsafe { init_from_closure(init) }
-}
-
-/// Initializes an array by initializing each element via the provided initializer.
-///
-/// # Examples
-///
-/// ```rust
-/// use kernel::{sync::{Arc, Mutex}, init::pin_init_array_from_fn, new_mutex};
-/// let array: Arc<[Mutex<usize>; 1_000]> =
-/// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i)), GFP_KERNEL)?;
-/// assert_eq!(array.len(), 1_000);
-/// # Ok::<(), Error>(())
-/// ```
-pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
- mut make_init: impl FnMut(usize) -> I,
-) -> impl PinInit<[T; N], E>
-where
- I: PinInit<T, E>,
-{
- let init = move |slot: *mut [T; N]| {
- let slot = slot.cast::<T>();
- // Counts the number of initialized elements and when dropped drops that many elements from
- // `slot`.
- let mut init_count = ScopeGuard::new_with_data(0, |i| {
- // We now free every element that has been initialized before.
- // SAFETY: The loop initialized exactly the values from 0..i and since we
- // return `Err` below, the caller will consider the memory at `slot` as
- // uninitialized.
- unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
- });
- for i in 0..N {
- let init = make_init(i);
- // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
- let ptr = unsafe { slot.add(i) };
- // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
- // requirements.
- unsafe { init.__pinned_init(ptr) }?;
- *init_count += 1;
- }
- init_count.dismiss();
- Ok(())
- };
- // SAFETY: The initializer above initializes every element of the array. On failure it drops
- // any initialized elements and returns `Err`.
- unsafe { pin_init_from_closure(init) }
-}
-
-// SAFETY: Every type can be initialized by-value.
-unsafe impl<T, E> Init<T, E> for T {
- unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
- // SAFETY: TODO.
- unsafe { slot.write(self) };
- Ok(())
- }
-}
-
-// SAFETY: Every type can be initialized by-value. `__pinned_init` calls `__init`.
-unsafe impl<T, E> PinInit<T, E> for T {
- unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
- // SAFETY: TODO.
- unsafe { self.__init(slot) }
- }
-}
-
-/// Smart pointer that can initialize memory in-place.
-pub trait InPlaceInit<T>: Sized {
- /// Pinned version of `Self`.
- ///
- /// If a type already implicitly pins its pointee, `Pin<Self>` is unnecessary. In this case use
- /// `Self`, otherwise just use `Pin<Self>`.
- type PinnedSelf;
-
- /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
- /// type.
- ///
- /// If `T: !Unpin` it will not be able to move afterwards.
- fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
- where
- E: From<AllocError>;
-
- /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
- /// type.
- ///
- /// If `T: !Unpin` it will not be able to move afterwards.
- fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf>
- where
- Error: From<E>,
- {
- // SAFETY: We delegate to `init` and only change the error type.
- let init = unsafe {
- pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
- };
- Self::try_pin_init(init, flags)
- }
-
- /// Use the given initializer to in-place initialize a `T`.
- fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
- where
- E: From<AllocError>;
-
- /// Use the given initializer to in-place initialize a `T`.
- fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
- where
- Error: From<E>,
- {
- // SAFETY: We delegate to `init` and only change the error type.
- let init = unsafe {
- init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
- };
- Self::try_init(init, flags)
- }
-}
-
-impl<T> InPlaceInit<T> for Arc<T> {
- type PinnedSelf = Self;
-
- #[inline]
- fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
- where
- E: From<AllocError>,
- {
- UniqueArc::try_pin_init(init, flags).map(|u| u.into())
- }
-
- #[inline]
- fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
- where
- E: From<AllocError>,
- {
- UniqueArc::try_init(init, flags).map(|u| u.into())
- }
-}
-
-impl<T> InPlaceInit<T> for UniqueArc<T> {
- type PinnedSelf = Pin<Self>;
-
- #[inline]
- fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
- where
- E: From<AllocError>,
- {
- UniqueArc::new_uninit(flags)?.write_pin_init(init)
- }
-
- #[inline]
- fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
- where
- E: From<AllocError>,
- {
- UniqueArc::new_uninit(flags)?.write_init(init)
- }
-}
-
-/// Smart pointer containing uninitialized memory and that can write a value.
-pub trait InPlaceWrite<T> {
- /// The type `Self` turns into when the contents are initialized.
- type Initialized;
-
- /// Use the given initializer to write a value into `self`.
- ///
- /// Does not drop the current value and considers it as uninitialized memory.
- fn write_init<E>(self, init: impl Init<T, E>) -> Result<Self::Initialized, E>;
-
- /// Use the given pin-initializer to write a value into `self`.
- ///
- /// Does not drop the current value and considers it as uninitialized memory.
- fn write_pin_init<E>(self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E>;
-}
-
-impl<T> InPlaceWrite<T> for UniqueArc<MaybeUninit<T>> {
- type Initialized = UniqueArc<T>;
-
- fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> {
- let slot = self.as_mut_ptr();
- // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
- // slot is valid.
- unsafe { init.__init(slot)? };
- // SAFETY: All fields have been initialized.
- Ok(unsafe { self.assume_init() })
- }
-
- fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> {
- let slot = self.as_mut_ptr();
- // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
- // slot is valid and will not be moved, because we pin it later.
- unsafe { init.__pinned_init(slot)? };
- // SAFETY: All fields have been initialized.
- Ok(unsafe { self.assume_init() }.into())
- }
-}
-
-/// Trait facilitating pinned destruction.
-///
-/// Use [`pinned_drop`] to implement this trait safely:
-///
-/// ```rust
-/// # use kernel::sync::Mutex;
-/// use kernel::macros::pinned_drop;
-/// use core::pin::Pin;
-/// #[pin_data(PinnedDrop)]
-/// struct Foo {
-/// #[pin]
-/// mtx: Mutex<usize>,
-/// }
-///
-/// #[pinned_drop]
-/// impl PinnedDrop for Foo {
-/// fn drop(self: Pin<&mut Self>) {
-/// pr_info!("Foo is being dropped!\n");
-/// }
-/// }
-/// ```
-///
-/// # Safety
-///
-/// This trait must be implemented via the [`pinned_drop`] proc-macro attribute on the impl.
-///
-/// [`pinned_drop`]: kernel::macros::pinned_drop
-pub unsafe trait PinnedDrop: __internal::HasPinData {
- /// Executes the pinned destructor of this type.
- ///
- /// While this function is marked safe, it is actually unsafe to call it manually. For this
- /// reason it takes an additional parameter. This type can only be constructed by `unsafe` code
- /// and thus prevents this function from being called where it should not.
- ///
- /// This extra parameter will be generated by the `#[pinned_drop]` proc-macro attribute
- /// automatically.
- fn drop(self: Pin<&mut Self>, only_call_from_drop: __internal::OnlyCallFromDrop);
-}
-
-/// Marker trait for types that can be initialized by writing just zeroes.
-///
-/// # Safety
-///
-/// The bit pattern consisting of only zeroes is a valid bit pattern for this type. In other words,
-/// this is not UB:
-///
-/// ```rust,ignore
-/// let val: Self = unsafe { core::mem::zeroed() };
-/// ```
-pub unsafe trait Zeroable {}
-
-/// Create a new zeroed T.
-///
-/// The returned initializer will write `0x00` to every byte of the given `slot`.
-#[inline]
-pub fn zeroed<T: Zeroable>() -> impl Init<T> {
- // SAFETY: Because `T: Zeroable`, all bytes zero is a valid bit pattern for `T`
- // and because we write all zeroes, the memory is initialized.
- unsafe {
- init_from_closure(|slot: *mut T| {
- slot.write_bytes(0, 1);
- Ok(())
- })
- }
-}
-
-macro_rules! impl_zeroable {
- ($($({$($generics:tt)*})? $t:ty, )*) => {
- // SAFETY: Safety comments written in the macro invocation.
- $(unsafe impl$($($generics)*)? Zeroable for $t {})*
- };
-}
-
-impl_zeroable! {
- // SAFETY: All primitives that are allowed to be zero.
- bool,
- char,
- u8, u16, u32, u64, u128, usize,
- i8, i16, i32, i64, i128, isize,
- f32, f64,
-
- // Note: do not add uninhabited types (such as `!` or `core::convert::Infallible`) to this list;
- // creating an instance of an uninhabited type is immediate undefined behavior. For more on
- // uninhabited/empty types, consult The Rustonomicon:
- // <https://doc.rust-lang.org/stable/nomicon/exotic-sizes.html#empty-types>. The Rust Reference
- // also has information on undefined behavior:
- // <https://doc.rust-lang.org/stable/reference/behavior-considered-undefined.html>.
- //
- // SAFETY: These are inhabited ZSTs; there is nothing to zero and a valid value exists.
- {<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, (),
-
- // SAFETY: Type is allowed to take any value, including all zeros.
- {<T>} MaybeUninit<T>,
- // SAFETY: Type is allowed to take any value, including all zeros.
- {<T>} Opaque<T>,
-
- // SAFETY: `T: Zeroable` and `UnsafeCell` is `repr(transparent)`.
- {<T: ?Sized + Zeroable>} UnsafeCell<T>,
-
- // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee:
- // https://doc.rust-lang.org/stable/std/option/index.html#representation).
- Option<NonZeroU8>, Option<NonZeroU16>, Option<NonZeroU32>, Option<NonZeroU64>,
- Option<NonZeroU128>, Option<NonZeroUsize>,
- Option<NonZeroI8>, Option<NonZeroI16>, Option<NonZeroI32>, Option<NonZeroI64>,
- Option<NonZeroI128>, Option<NonZeroIsize>,
- {<T>} Option<NonNull<T>>,
- {<T>} Option<KBox<T>>,
-
- // SAFETY: `null` pointer is valid.
- //
- // We cannot use `T: ?Sized`, since the VTABLE pointer part of fat pointers is not allowed to be
- // null.
- //
- // When `Pointee` gets stabilized, we could use
- // `T: ?Sized where <T as Pointee>::Metadata: Zeroable`
- {<T>} *mut T, {<T>} *const T,
-
- // SAFETY: `null` pointer is valid and the metadata part of these fat pointers is allowed to be
- // zero.
- {<T>} *mut [T], {<T>} *const [T], *mut str, *const str,
-
- // SAFETY: `T` is `Zeroable`.
- {<const N: usize, T: Zeroable>} [T; N], {<T: Zeroable>} Wrapping<T>,
-}
-
-macro_rules! impl_tuple_zeroable {
- ($(,)?) => {};
- ($first:ident, $($t:ident),* $(,)?) => {
- // SAFETY: All elements are zeroable and padding can be zero.
- unsafe impl<$first: Zeroable, $($t: Zeroable),*> Zeroable for ($first, $($t),*) {}
- impl_tuple_zeroable!($($t),* ,);
- }
-}
-
-impl_tuple_zeroable!(A, B, C, D, E, F, G, H, I, J);
diff --git a/rust/kernel/init/__internal.rs b/rust/kernel/init/__internal.rs
deleted file mode 100644
index 74329cc3262c..000000000000
--- a/rust/kernel/init/__internal.rs
+++ /dev/null
@@ -1,264 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR MIT
-
-//! This module contains API-internal items for pin-init.
-//!
-//! These items must not be used outside of
-//! - `kernel/init.rs`
-//! - `macros/pin_data.rs`
-//! - `macros/pinned_drop.rs`
-
-use super::*;
-
-/// See the [nomicon] for what subtyping is. See also [this table].
-///
-/// [nomicon]: https://doc.rust-lang.org/nomicon/subtyping.html
-/// [this table]: https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns
-pub(super) type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>;
-
-/// Module-internal type implementing `PinInit` and `Init`.
-///
-/// It is unsafe to create this type, since the closure needs to fulfill the same safety
-/// requirement as the `__pinned_init`/`__init` functions.
-pub(crate) struct InitClosure<F, T: ?Sized, E>(pub(crate) F, pub(crate) Invariant<(E, T)>);
-
-// SAFETY: While constructing the `InitClosure`, the user promised that it upholds the
-// `__init` invariants.
-unsafe impl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T, E>
-where
- F: FnOnce(*mut T) -> Result<(), E>,
-{
- #[inline]
- unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
- (self.0)(slot)
- }
-}
-
-// SAFETY: While constructing the `InitClosure`, the user promised that it upholds the
-// `__pinned_init` invariants.
-unsafe impl<T: ?Sized, F, E> PinInit<T, E> for InitClosure<F, T, E>
-where
- F: FnOnce(*mut T) -> Result<(), E>,
-{
- #[inline]
- unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
- (self.0)(slot)
- }
-}
-
-/// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate
-/// the pin projections within the initializers.
-///
-/// # Safety
-///
-/// Only the `init` module is allowed to use this trait.
-pub unsafe trait HasPinData {
- type PinData: PinData;
-
- #[expect(clippy::missing_safety_doc)]
- unsafe fn __pin_data() -> Self::PinData;
-}
-
-/// Marker trait for pinning data of structs.
-///
-/// # Safety
-///
-/// Only the `init` module is allowed to use this trait.
-pub unsafe trait PinData: Copy {
- type Datee: ?Sized + HasPinData;
-
- /// Type inference helper function.
- fn make_closure<F, O, E>(self, f: F) -> F
- where
- F: FnOnce(*mut Self::Datee) -> Result<O, E>,
- {
- f
- }
-}
-
-/// This trait is automatically implemented for every type. It aims to provide the same type
-/// inference help as `HasPinData`.
-///
-/// # Safety
-///
-/// Only the `init` module is allowed to use this trait.
-pub unsafe trait HasInitData {
- type InitData: InitData;
-
- #[expect(clippy::missing_safety_doc)]
- unsafe fn __init_data() -> Self::InitData;
-}
-
-/// Same function as `PinData`, but for arbitrary data.
-///
-/// # Safety
-///
-/// Only the `init` module is allowed to use this trait.
-pub unsafe trait InitData: Copy {
- type Datee: ?Sized + HasInitData;
-
- /// Type inference helper function.
- fn make_closure<F, O, E>(self, f: F) -> F
- where
- F: FnOnce(*mut Self::Datee) -> Result<O, E>,
- {
- f
- }
-}
-
-pub struct AllData<T: ?Sized>(PhantomData<fn(KBox<T>) -> KBox<T>>);
-
-impl<T: ?Sized> Clone for AllData<T> {
- fn clone(&self) -> Self {
- *self
- }
-}
-
-impl<T: ?Sized> Copy for AllData<T> {}
-
-// SAFETY: TODO.
-unsafe impl<T: ?Sized> InitData for AllData<T> {
- type Datee = T;
-}
-
-// SAFETY: TODO.
-unsafe impl<T: ?Sized> HasInitData for T {
- type InitData = AllData<T>;
-
- unsafe fn __init_data() -> Self::InitData {
- AllData(PhantomData)
- }
-}
-
-/// Stack initializer helper type. Use [`stack_pin_init`] instead of this primitive.
-///
-/// # Invariants
-///
-/// If `self.is_init` is true, then `self.value` is initialized.
-///
-/// [`stack_pin_init`]: kernel::stack_pin_init
-pub struct StackInit<T> {
- value: MaybeUninit<T>,
- is_init: bool,
-}
-
-impl<T> Drop for StackInit<T> {
- #[inline]
- fn drop(&mut self) {
- if self.is_init {
- // SAFETY: As we are being dropped, we only call this once. And since `self.is_init` is
- // true, `self.value` is initialized.
- unsafe { self.value.assume_init_drop() };
- }
- }
-}
-
-impl<T> StackInit<T> {
- /// Creates a new [`StackInit<T>`] that is uninitialized. Use [`stack_pin_init`] instead of this
- /// primitive.
- ///
- /// [`stack_pin_init`]: kernel::stack_pin_init
- #[inline]
- pub fn uninit() -> Self {
- Self {
- value: MaybeUninit::uninit(),
- is_init: false,
- }
- }
-
- /// Initializes the contents and returns the result.
- #[inline]
- pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mut T>, E> {
- // SAFETY: We never move out of `this`.
- let this = unsafe { Pin::into_inner_unchecked(self) };
- // The value is currently initialized, so it needs to be dropped before we can reuse
- // the memory (this is a safety guarantee of `Pin`).
- if this.is_init {
- this.is_init = false;
- // SAFETY: `this.is_init` was true and therefore `this.value` is initialized.
- unsafe { this.value.assume_init_drop() };
- }
- // SAFETY: The memory slot is valid and this type ensures that it will stay pinned.
- unsafe { init.__pinned_init(this.value.as_mut_ptr())? };
- // INVARIANT: `this.value` is initialized above.
- this.is_init = true;
- // SAFETY: The slot is now pinned, since we will never give access to `&mut T`.
- Ok(unsafe { Pin::new_unchecked(this.value.assume_init_mut()) })
- }
-}
-
-/// When a value of this type is dropped, it drops a `T`.
-///
-/// Can be forgotten to prevent the drop.
-pub struct DropGuard<T: ?Sized> {
- ptr: *mut T,
-}
-
-impl<T: ?Sized> DropGuard<T> {
- /// Creates a new [`DropGuard<T>`]. It will [`ptr::drop_in_place`] `ptr` when it gets dropped.
- ///
- /// # Safety
- ///
- /// `ptr` must be a valid pointer.
- ///
- /// It is the callers responsibility that `self` will only get dropped if the pointee of `ptr`:
- /// - has not been dropped,
- /// - is not accessible by any other means,
- /// - will not be dropped by any other means.
- #[inline]
- pub unsafe fn new(ptr: *mut T) -> Self {
- Self { ptr }
- }
-}
-
-impl<T: ?Sized> Drop for DropGuard<T> {
- #[inline]
- fn drop(&mut self) {
- // SAFETY: A `DropGuard` can only be constructed using the unsafe `new` function
- // ensuring that this operation is safe.
- unsafe { ptr::drop_in_place(self.ptr) }
- }
-}
-
-/// Token used by `PinnedDrop` to prevent calling the function without creating this unsafely
-/// created struct. This is needed, because the `drop` function is safe, but should not be called
-/// manually.
-pub struct OnlyCallFromDrop(());
-
-impl OnlyCallFromDrop {
- /// # Safety
- ///
- /// This function should only be called from the [`Drop::drop`] function and only be used to
- /// delegate the destruction to the pinned destructor [`PinnedDrop::drop`] of the same type.
- pub unsafe fn new() -> Self {
- Self(())
- }
-}
-
-/// Initializer that always fails.
-///
-/// Used by [`assert_pinned!`].
-///
-/// [`assert_pinned!`]: crate::assert_pinned
-pub struct AlwaysFail<T: ?Sized> {
- _t: PhantomData<T>,
-}
-
-impl<T: ?Sized> AlwaysFail<T> {
- /// Creates a new initializer that always fails.
- pub fn new() -> Self {
- Self { _t: PhantomData }
- }
-}
-
-impl<T: ?Sized> Default for AlwaysFail<T> {
- fn default() -> Self {
- Self::new()
- }
-}
-
-// SAFETY: `__pinned_init` always fails, which is always okay.
-unsafe impl<T: ?Sized> PinInit<T, ()> for AlwaysFail<T> {
- unsafe fn __pinned_init(self, _slot: *mut T) -> Result<(), ()> {
- Err(())
- }
-}
diff --git a/rust/kernel/init/macros.rs b/rust/kernel/init/macros.rs
deleted file mode 100644
index b7213962a6a5..000000000000
--- a/rust/kernel/init/macros.rs
+++ /dev/null
@@ -1,1410 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR MIT
-
-//! This module provides the macros that actually implement the proc-macros `pin_data` and
-//! `pinned_drop`. It also contains `__init_internal` the implementation of the `{try_}{pin_}init!`
-//! macros.
-//!
-//! These macros should never be called directly, since they expect their input to be
-//! in a certain format which is internal. If used incorrectly, these macros can lead to UB even in
-//! safe code! Use the public facing macros instead.
-//!
-//! This architecture has been chosen because the kernel does not yet have access to `syn` which
-//! would make matters a lot easier for implementing these as proc-macros.
-//!
-//! # Macro expansion example
-//!
-//! This section is intended for readers trying to understand the macros in this module and the
-//! `pin_init!` macros from `init.rs`.
-//!
-//! We will look at the following example:
-//!
-//! ```rust,ignore
-//! # use kernel::init::*;
-//! # use core::pin::Pin;
-//! #[pin_data]
-//! #[repr(C)]
-//! struct Bar<T> {
-//! #[pin]
-//! t: T,
-//! pub x: usize,
-//! }
-//!
-//! impl<T> Bar<T> {
-//! fn new(t: T) -> impl PinInit<Self> {
-//! pin_init!(Self { t, x: 0 })
-//! }
-//! }
-//!
-//! #[pin_data(PinnedDrop)]
-//! struct Foo {
-//! a: usize,
-//! #[pin]
-//! b: Bar<u32>,
-//! }
-//!
-//! #[pinned_drop]
-//! impl PinnedDrop for Foo {
-//! fn drop(self: Pin<&mut Self>) {
-//! pr_info!("{self:p} is getting dropped.\n");
-//! }
-//! }
-//!
-//! let a = 42;
-//! let initializer = pin_init!(Foo {
-//! a,
-//! b <- Bar::new(36),
-//! });
-//! ```
-//!
-//! This example includes the most common and important features of the pin-init API.
-//!
-//! Below you can find individual section about the different macro invocations. Here are some
-//! general things we need to take into account when designing macros:
-//! - use global paths, similarly to file paths, these start with the separator: `::core::panic!()`
-//! this ensures that the correct item is used, since users could define their own `mod core {}`
-//! and then their own `panic!` inside to execute arbitrary code inside of our macro.
-//! - macro `unsafe` hygiene: we need to ensure that we do not expand arbitrary, user-supplied
-//! expressions inside of an `unsafe` block in the macro, because this would allow users to do
-//! `unsafe` operations without an associated `unsafe` block.
-//!
-//! ## `#[pin_data]` on `Bar`
-//!
-//! This macro is used to specify which fields are structurally pinned and which fields are not. It
-//! is placed on the struct definition and allows `#[pin]` to be placed on the fields.
-//!
-//! Here is the definition of `Bar` from our example:
-//!
-//! ```rust,ignore
-//! # use kernel::init::*;
-//! #[pin_data]
-//! #[repr(C)]
-//! struct Bar<T> {
-//! #[pin]
-//! t: T,
-//! pub x: usize,
-//! }
-//! ```
-//!
-//! This expands to the following code:
-//!
-//! ```rust,ignore
-//! // Firstly the normal definition of the struct, attributes are preserved:
-//! #[repr(C)]
-//! struct Bar<T> {
-//! t: T,
-//! pub x: usize,
-//! }
-//! // Then an anonymous constant is defined, this is because we do not want any code to access the
-//! // types that we define inside:
-//! const _: () = {
-//! // We define the pin-data carrying struct, it is a ZST and needs to have the same generics,
-//! // since we need to implement access functions for each field and thus need to know its
-//! // type.
-//! struct __ThePinData<T> {
-//! __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>,
-//! }
-//! // We implement `Copy` for the pin-data struct, since all functions it defines will take
-//! // `self` by value.
-//! impl<T> ::core::clone::Clone for __ThePinData<T> {
-//! fn clone(&self) -> Self {
-//! *self
-//! }
-//! }
-//! impl<T> ::core::marker::Copy for __ThePinData<T> {}
-//! // For every field of `Bar`, the pin-data struct will define a function with the same name
-//! // and accessor (`pub` or `pub(crate)` etc.). This function will take a pointer to the
-//! // field (`slot`) and a `PinInit` or `Init` depending on the projection kind of the field
-//! // (if pinning is structural for the field, then `PinInit` otherwise `Init`).
-//! #[allow(dead_code)]
-//! impl<T> __ThePinData<T> {
-//! unsafe fn t<E>(
-//! self,
-//! slot: *mut T,
-//! // Since `t` is `#[pin]`, this is `PinInit`.
-//! init: impl ::kernel::init::PinInit<T, E>,
-//! ) -> ::core::result::Result<(), E> {
-//! unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) }
-//! }
-//! pub unsafe fn x<E>(
-//! self,
-//! slot: *mut usize,
-//! // Since `x` is not `#[pin]`, this is `Init`.
-//! init: impl ::kernel::init::Init<usize, E>,
-//! ) -> ::core::result::Result<(), E> {
-//! unsafe { ::kernel::init::Init::__init(init, slot) }
-//! }
-//! }
-//! // Implement the internal `HasPinData` trait that associates `Bar` with the pin-data struct
-//! // that we constructed above.
-//! unsafe impl<T> ::kernel::init::__internal::HasPinData for Bar<T> {
-//! type PinData = __ThePinData<T>;
-//! unsafe fn __pin_data() -> Self::PinData {
-//! __ThePinData {
-//! __phantom: ::core::marker::PhantomData,
-//! }
-//! }
-//! }
-//! // Implement the internal `PinData` trait that marks the pin-data struct as a pin-data
-//! // struct. This is important to ensure that no user can implement a rogue `__pin_data`
-//! // function without using `unsafe`.
-//! unsafe impl<T> ::kernel::init::__internal::PinData for __ThePinData<T> {
-//! type Datee = Bar<T>;
-//! }
-//! // Now we only want to implement `Unpin` for `Bar` when every structurally pinned field is
-//! // `Unpin`. In other words, whether `Bar` is `Unpin` only depends on structurally pinned
-//! // fields (those marked with `#[pin]`). These fields will be listed in this struct, in our
-//! // case no such fields exist, hence this is almost empty. The two phantomdata fields exist
-//! // for two reasons:
-//! // - `__phantom`: every generic must be used, since we cannot really know which generics
-//! // are used, we declare all and then use everything here once.
-//! // - `__phantom_pin`: uses the `'__pin` lifetime and ensures that this struct is invariant
-//! // over it. The lifetime is needed to work around the limitation that trait bounds must
-//! // not be trivial, e.g. the user has a `#[pin] PhantomPinned` field -- this is
-//! // unconditionally `!Unpin` and results in an error. The lifetime tricks the compiler
-//! // into accepting these bounds regardless.
-//! #[allow(dead_code)]
-//! struct __Unpin<'__pin, T> {
-//! __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
-//! __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>,
-//! // Our only `#[pin]` field is `t`.
-//! t: T,
-//! }
-//! #[doc(hidden)]
-//! impl<'__pin, T> ::core::marker::Unpin for Bar<T>
-//! where
-//! __Unpin<'__pin, T>: ::core::marker::Unpin,
-//! {}
-//! // Now we need to ensure that `Bar` does not implement `Drop`, since that would give users
-//! // access to `&mut self` inside of `drop` even if the struct was pinned. This could lead to
-//! // UB with only safe code, so we disallow this by giving a trait implementation error using
-//! // a direct impl and a blanket implementation.
-//! trait MustNotImplDrop {}
-//! // Normally `Drop` bounds do not have the correct semantics, but for this purpose they do
-//! // (normally people want to know if a type has any kind of drop glue at all, here we want
-//! // to know if it has any kind of custom drop glue, which is exactly what this bound does).
-//! #[expect(drop_bounds)]
-//! impl<T: ::core::ops::Drop> MustNotImplDrop for T {}
-//! impl<T> MustNotImplDrop for Bar<T> {}
-//! // Here comes a convenience check, if one implemented `PinnedDrop`, but forgot to add it to
-//! // `#[pin_data]`, then this will error with the same mechanic as above, this is not needed
-//! // for safety, but a good sanity check, since no normal code calls `PinnedDrop::drop`.
-//! #[expect(non_camel_case_types)]
-//! trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
-//! impl<
-//! T: ::kernel::init::PinnedDrop,
-//! > UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
-//! impl<T> UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for Bar<T> {}
-//! };
-//! ```
-//!
-//! ## `pin_init!` in `impl Bar`
-//!
-//! This macro creates an pin-initializer for the given struct. It requires that the struct is
-//! annotated by `#[pin_data]`.
-//!
-//! Here is the impl on `Bar` defining the new function:
-//!
-//! ```rust,ignore
-//! impl<T> Bar<T> {
-//! fn new(t: T) -> impl PinInit<Self> {
-//! pin_init!(Self { t, x: 0 })
-//! }
-//! }
-//! ```
-//!
-//! This expands to the following code:
-//!
-//! ```rust,ignore
-//! impl<T> Bar<T> {
-//! fn new(t: T) -> impl PinInit<Self> {
-//! {
-//! // We do not want to allow arbitrary returns, so we declare this type as the `Ok`
-//! // return type and shadow it later when we insert the arbitrary user code. That way
-//! // there will be no possibility of returning without `unsafe`.
-//! struct __InitOk;
-//! // Get the data about fields from the supplied type.
-//! // - the function is unsafe, hence the unsafe block
-//! // - we `use` the `HasPinData` trait in the block, it is only available in that
-//! // scope.
-//! let data = unsafe {
-//! use ::kernel::init::__internal::HasPinData;
-//! Self::__pin_data()
-//! };
-//! // Ensure that `data` really is of type `PinData` and help with type inference:
-//! let init = ::kernel::init::__internal::PinData::make_closure::<
-//! _,
-//! __InitOk,
-//! ::core::convert::Infallible,
-//! >(data, move |slot| {
-//! {
-//! // Shadow the structure so it cannot be used to return early. If a user
-//! // tries to write `return Ok(__InitOk)`, then they get a type error,
-//! // since that will refer to this struct instead of the one defined
-//! // above.
-//! struct __InitOk;
-//! // This is the expansion of `t,`, which is syntactic sugar for `t: t,`.
-//! {
-//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) };
-//! }
-//! // Since initialization could fail later (not in this case, since the
-//! // error type is `Infallible`) we will need to drop this field if there
-//! // is an error later. This `DropGuard` will drop the field when it gets
-//! // dropped and has not yet been forgotten.
-//! let __t_guard = unsafe {
-//! ::pinned_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t))
-//! };
-//! // Expansion of `x: 0,`:
-//! // Since this can be an arbitrary expression we cannot place it inside
-//! // of the `unsafe` block, so we bind it here.
-//! {
-//! let x = 0;
-//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) };
-//! }
-//! // We again create a `DropGuard`.
-//! let __x_guard = unsafe {
-//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).x))
-//! };
-//! // Since initialization has successfully completed, we can now forget
-//! // the guards. This is not `mem::forget`, since we only have
-//! // `&DropGuard`.
-//! ::core::mem::forget(__x_guard);
-//! ::core::mem::forget(__t_guard);
-//! // Here we use the type checker to ensure that every field has been
-//! // initialized exactly once, since this is `if false` it will never get
-//! // executed, but still type-checked.
-//! // Additionally we abuse `slot` to automatically infer the correct type
-//! // for the struct. This is also another check that every field is
-//! // accessible from this scope.
-//! #[allow(unreachable_code, clippy::diverging_sub_expression)]
-//! let _ = || {
-//! unsafe {
-//! ::core::ptr::write(
-//! slot,
-//! Self {
-//! // We only care about typecheck finding every field
-//! // here, the expression does not matter, just conjure
-//! // one using `panic!()`:
-//! t: ::core::panic!(),
-//! x: ::core::panic!(),
-//! },
-//! );
-//! };
-//! };
-//! }
-//! // We leave the scope above and gain access to the previously shadowed
-//! // `__InitOk` that we need to return.
-//! Ok(__InitOk)
-//! });
-//! // Change the return type from `__InitOk` to `()`.
-//! let init = move |
-//! slot,
-//! | -> ::core::result::Result<(), ::core::convert::Infallible> {
-//! init(slot).map(|__InitOk| ())
-//! };
-//! // Construct the initializer.
-//! let init = unsafe {
-//! ::kernel::init::pin_init_from_closure::<
-//! _,
-//! ::core::convert::Infallible,
-//! >(init)
-//! };
-//! init
-//! }
-//! }
-//! }
-//! ```
-//!
-//! ## `#[pin_data]` on `Foo`
-//!
-//! Since we already took a look at `#[pin_data]` on `Bar`, this section will only explain the
-//! differences/new things in the expansion of the `Foo` definition:
-//!
-//! ```rust,ignore
-//! #[pin_data(PinnedDrop)]
-//! struct Foo {
-//! a: usize,
-//! #[pin]
-//! b: Bar<u32>,
-//! }
-//! ```
-//!
-//! This expands to the following code:
-//!
-//! ```rust,ignore
-//! struct Foo {
-//! a: usize,
-//! b: Bar<u32>,
-//! }
-//! const _: () = {
-//! struct __ThePinData {
-//! __phantom: ::core::marker::PhantomData<fn(Foo) -> Foo>,
-//! }
-//! impl ::core::clone::Clone for __ThePinData {
-//! fn clone(&self) -> Self {
-//! *self
-//! }
-//! }
-//! impl ::core::marker::Copy for __ThePinData {}
-//! #[allow(dead_code)]
-//! impl __ThePinData {
-//! unsafe fn b<E>(
-//! self,
-//! slot: *mut Bar<u32>,
-//! init: impl ::kernel::init::PinInit<Bar<u32>, E>,
-//! ) -> ::core::result::Result<(), E> {
-//! unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) }
-//! }
-//! unsafe fn a<E>(
-//! self,
-//! slot: *mut usize,
-//! init: impl ::kernel::init::Init<usize, E>,
-//! ) -> ::core::result::Result<(), E> {
-//! unsafe { ::kernel::init::Init::__init(init, slot) }
-//! }
-//! }
-//! unsafe impl ::kernel::init::__internal::HasPinData for Foo {
-//! type PinData = __ThePinData;
-//! unsafe fn __pin_data() -> Self::PinData {
-//! __ThePinData {
-//! __phantom: ::core::marker::PhantomData,
-//! }
-//! }
-//! }
-//! unsafe impl ::kernel::init::__internal::PinData for __ThePinData {
-//! type Datee = Foo;
-//! }
-//! #[allow(dead_code)]
-//! struct __Unpin<'__pin> {
-//! __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
-//! __phantom: ::core::marker::PhantomData<fn(Foo) -> Foo>,
-//! b: Bar<u32>,
-//! }
-//! #[doc(hidden)]
-//! impl<'__pin> ::core::marker::Unpin for Foo
-//! where
-//! __Unpin<'__pin>: ::core::marker::Unpin,
-//! {}
-//! // Since we specified `PinnedDrop` as the argument to `#[pin_data]`, we expect `Foo` to
-//! // implement `PinnedDrop`. Thus we do not need to prevent `Drop` implementations like
-//! // before, instead we implement `Drop` here and delegate to `PinnedDrop`.
-//! impl ::core::ops::Drop for Foo {
-//! fn drop(&mut self) {
-//! // Since we are getting dropped, no one else has a reference to `self` and thus we
-//! // can assume that we never move.
-//! let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) };
-//! // Create the unsafe token that proves that we are inside of a destructor, this
-//! // type is only allowed to be created in a destructor.
-//! let token = unsafe { ::kernel::init::__internal::OnlyCallFromDrop::new() };
-//! ::kernel::init::PinnedDrop::drop(pinned, token);
-//! }
-//! }
-//! };
-//! ```
-//!
-//! ## `#[pinned_drop]` on `impl PinnedDrop for Foo`
-//!
-//! This macro is used to implement the `PinnedDrop` trait, since that trait is `unsafe` and has an
-//! extra parameter that should not be used at all. The macro hides that parameter.
-//!
-//! Here is the `PinnedDrop` impl for `Foo`:
-//!
-//! ```rust,ignore
-//! #[pinned_drop]
-//! impl PinnedDrop for Foo {
-//! fn drop(self: Pin<&mut Self>) {
-//! pr_info!("{self:p} is getting dropped.\n");
-//! }
-//! }
-//! ```
-//!
-//! This expands to the following code:
-//!
-//! ```rust,ignore
-//! // `unsafe`, full path and the token parameter are added, everything else stays the same.
-//! unsafe impl ::kernel::init::PinnedDrop for Foo {
-//! fn drop(self: Pin<&mut Self>, _: ::kernel::init::__internal::OnlyCallFromDrop) {
-//! pr_info!("{self:p} is getting dropped.\n");
-//! }
-//! }
-//! ```
-//!
-//! ## `pin_init!` on `Foo`
-//!
-//! Since we already took a look at `pin_init!` on `Bar`, this section will only show the expansion
-//! of `pin_init!` on `Foo`:
-//!
-//! ```rust,ignore
-//! let a = 42;
-//! let initializer = pin_init!(Foo {
-//! a,
-//! b <- Bar::new(36),
-//! });
-//! ```
-//!
-//! This expands to the following code:
-//!
-//! ```rust,ignore
-//! let a = 42;
-//! let initializer = {
-//! struct __InitOk;
-//! let data = unsafe {
-//! use ::kernel::init::__internal::HasPinData;
-//! Foo::__pin_data()
-//! };
-//! let init = ::kernel::init::__internal::PinData::make_closure::<
-//! _,
-//! __InitOk,
-//! ::core::convert::Infallible,
-//! >(data, move |slot| {
-//! {
-//! struct __InitOk;
-//! {
-//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) };
-//! }
-//! let __a_guard = unsafe {
-//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a))
-//! };
-//! let init = Bar::new(36);
-//! unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? };
-//! let __b_guard = unsafe {
-//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b))
-//! };
-//! ::core::mem::forget(__b_guard);
-//! ::core::mem::forget(__a_guard);
-//! #[allow(unreachable_code, clippy::diverging_sub_expression)]
-//! let _ = || {
-//! unsafe {
-//! ::core::ptr::write(
-//! slot,
-//! Foo {
-//! a: ::core::panic!(),
-//! b: ::core::panic!(),
-//! },
-//! );
-//! };
-//! };
-//! }
-//! Ok(__InitOk)
-//! });
-//! let init = move |
-//! slot,
-//! | -> ::core::result::Result<(), ::core::convert::Infallible> {
-//! init(slot).map(|__InitOk| ())
-//! };
-//! let init = unsafe {
-//! ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init)
-//! };
-//! init
-//! };
-//! ```
-
-/// Creates a `unsafe impl<...> PinnedDrop for $type` block.
-///
-/// See [`PinnedDrop`] for more information.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __pinned_drop {
- (
- @impl_sig($($impl_sig:tt)*),
- @impl_body(
- $(#[$($attr:tt)*])*
- fn drop($($sig:tt)*) {
- $($inner:tt)*
- }
- ),
- ) => {
- // SAFETY: TODO.
- unsafe $($impl_sig)* {
- // Inherit all attributes and the type/ident tokens for the signature.
- $(#[$($attr)*])*
- fn drop($($sig)*, _: $crate::init::__internal::OnlyCallFromDrop) {
- $($inner)*
- }
- }
- }
-}
-
-/// This macro first parses the struct definition such that it separates pinned and not pinned
-/// fields. Afterwards it declares the struct and implement the `PinData` trait safely.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __pin_data {
- // Proc-macro entry point, this is supplied by the proc-macro pre-parsing.
- (parse_input:
- @args($($pinned_drop:ident)?),
- @sig(
- $(#[$($struct_attr:tt)*])*
- $vis:vis struct $name:ident
- $(where $($whr:tt)*)?
- ),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @decl_generics($($decl_generics:tt)*),
- @body({ $($fields:tt)* }),
- ) => {
- // We now use token munching to iterate through all of the fields. While doing this we
- // identify fields marked with `#[pin]`, these fields are the 'pinned fields'. The user
- // wants these to be structurally pinned. The rest of the fields are the
- // 'not pinned fields'. Additionally we collect all fields, since we need them in the right
- // order to declare the struct.
- //
- // In this call we also put some explaining comments for the parameters.
- $crate::__pin_data!(find_pinned_fields:
- // Attributes on the struct itself, these will just be propagated to be put onto the
- // struct definition.
- @struct_attrs($(#[$($struct_attr)*])*),
- // The visibility of the struct.
- @vis($vis),
- // The name of the struct.
- @name($name),
- // The 'impl generics', the generics that will need to be specified on the struct inside
- // of an `impl<$ty_generics>` block.
- @impl_generics($($impl_generics)*),
- // The 'ty generics', the generics that will need to be specified on the impl blocks.
- @ty_generics($($ty_generics)*),
- // The 'decl generics', the generics that need to be specified on the struct
- // definition.
- @decl_generics($($decl_generics)*),
- // The where clause of any impl block and the declaration.
- @where($($($whr)*)?),
- // The remaining fields tokens that need to be processed.
- // We add a `,` at the end to ensure correct parsing.
- @fields_munch($($fields)* ,),
- // The pinned fields.
- @pinned(),
- // The not pinned fields.
- @not_pinned(),
- // All fields.
- @fields(),
- // The accumulator containing all attributes already parsed.
- @accum(),
- // Contains `yes` or `` to indicate if `#[pin]` was found on the current field.
- @is_pinned(),
- // The proc-macro argument, this should be `PinnedDrop` or ``.
- @pinned_drop($($pinned_drop)?),
- );
- };
- (find_pinned_fields:
- @struct_attrs($($struct_attrs:tt)*),
- @vis($vis:vis),
- @name($name:ident),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @decl_generics($($decl_generics:tt)*),
- @where($($whr:tt)*),
- // We found a PhantomPinned field, this should generally be pinned!
- @fields_munch($field:ident : $($($(::)?core::)?marker::)?PhantomPinned, $($rest:tt)*),
- @pinned($($pinned:tt)*),
- @not_pinned($($not_pinned:tt)*),
- @fields($($fields:tt)*),
- @accum($($accum:tt)*),
- // This field is not pinned.
- @is_pinned(),
- @pinned_drop($($pinned_drop:ident)?),
- ) => {
- ::core::compile_error!(concat!(
- "The field `",
- stringify!($field),
- "` of type `PhantomPinned` only has an effect, if it has the `#[pin]` attribute.",
- ));
- $crate::__pin_data!(find_pinned_fields:
- @struct_attrs($($struct_attrs)*),
- @vis($vis),
- @name($name),
- @impl_generics($($impl_generics)*),
- @ty_generics($($ty_generics)*),
- @decl_generics($($decl_generics)*),
- @where($($whr)*),
- @fields_munch($($rest)*),
- @pinned($($pinned)* $($accum)* $field: ::core::marker::PhantomPinned,),
- @not_pinned($($not_pinned)*),
- @fields($($fields)* $($accum)* $field: ::core::marker::PhantomPinned,),
- @accum(),
- @is_pinned(),
- @pinned_drop($($pinned_drop)?),
- );
- };
- (find_pinned_fields:
- @struct_attrs($($struct_attrs:tt)*),
- @vis($vis:vis),
- @name($name:ident),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @decl_generics($($decl_generics:tt)*),
- @where($($whr:tt)*),
- // We reached the field declaration.
- @fields_munch($field:ident : $type:ty, $($rest:tt)*),
- @pinned($($pinned:tt)*),
- @not_pinned($($not_pinned:tt)*),
- @fields($($fields:tt)*),
- @accum($($accum:tt)*),
- // This field is pinned.
- @is_pinned(yes),
- @pinned_drop($($pinned_drop:ident)?),
- ) => {
- $crate::__pin_data!(find_pinned_fields:
- @struct_attrs($($struct_attrs)*),
- @vis($vis),
- @name($name),
- @impl_generics($($impl_generics)*),
- @ty_generics($($ty_generics)*),
- @decl_generics($($decl_generics)*),
- @where($($whr)*),
- @fields_munch($($rest)*),
- @pinned($($pinned)* $($accum)* $field: $type,),
- @not_pinned($($not_pinned)*),
- @fields($($fields)* $($accum)* $field: $type,),
- @accum(),
- @is_pinned(),
- @pinned_drop($($pinned_drop)?),
- );
- };
- (find_pinned_fields:
- @struct_attrs($($struct_attrs:tt)*),
- @vis($vis:vis),
- @name($name:ident),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @decl_generics($($decl_generics:tt)*),
- @where($($whr:tt)*),
- // We reached the field declaration.
- @fields_munch($field:ident : $type:ty, $($rest:tt)*),
- @pinned($($pinned:tt)*),
- @not_pinned($($not_pinned:tt)*),
- @fields($($fields:tt)*),
- @accum($($accum:tt)*),
- // This field is not pinned.
- @is_pinned(),
- @pinned_drop($($pinned_drop:ident)?),
- ) => {
- $crate::__pin_data!(find_pinned_fields:
- @struct_attrs($($struct_attrs)*),
- @vis($vis),
- @name($name),
- @impl_generics($($impl_generics)*),
- @ty_generics($($ty_generics)*),
- @decl_generics($($decl_generics)*),
- @where($($whr)*),
- @fields_munch($($rest)*),
- @pinned($($pinned)*),
- @not_pinned($($not_pinned)* $($accum)* $field: $type,),
- @fields($($fields)* $($accum)* $field: $type,),
- @accum(),
- @is_pinned(),
- @pinned_drop($($pinned_drop)?),
- );
- };
- (find_pinned_fields:
- @struct_attrs($($struct_attrs:tt)*),
- @vis($vis:vis),
- @name($name:ident),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @decl_generics($($decl_generics:tt)*),
- @where($($whr:tt)*),
- // We found the `#[pin]` attr.
- @fields_munch(#[pin] $($rest:tt)*),
- @pinned($($pinned:tt)*),
- @not_pinned($($not_pinned:tt)*),
- @fields($($fields:tt)*),
- @accum($($accum:tt)*),
- @is_pinned($($is_pinned:ident)?),
- @pinned_drop($($pinned_drop:ident)?),
- ) => {
- $crate::__pin_data!(find_pinned_fields:
- @struct_attrs($($struct_attrs)*),
- @vis($vis),
- @name($name),
- @impl_generics($($impl_generics)*),
- @ty_generics($($ty_generics)*),
- @decl_generics($($decl_generics)*),
- @where($($whr)*),
- @fields_munch($($rest)*),
- // We do not include `#[pin]` in the list of attributes, since it is not actually an
- // attribute that is defined somewhere.
- @pinned($($pinned)*),
- @not_pinned($($not_pinned)*),
- @fields($($fields)*),
- @accum($($accum)*),
- // Set this to `yes`.
- @is_pinned(yes),
- @pinned_drop($($pinned_drop)?),
- );
- };
- (find_pinned_fields:
- @struct_attrs($($struct_attrs:tt)*),
- @vis($vis:vis),
- @name($name:ident),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @decl_generics($($decl_generics:tt)*),
- @where($($whr:tt)*),
- // We reached the field declaration with visibility, for simplicity we only munch the
- // visibility and put it into `$accum`.
- @fields_munch($fvis:vis $field:ident $($rest:tt)*),
- @pinned($($pinned:tt)*),
- @not_pinned($($not_pinned:tt)*),
- @fields($($fields:tt)*),
- @accum($($accum:tt)*),
- @is_pinned($($is_pinned:ident)?),
- @pinned_drop($($pinned_drop:ident)?),
- ) => {
- $crate::__pin_data!(find_pinned_fields:
- @struct_attrs($($struct_attrs)*),
- @vis($vis),
- @name($name),
- @impl_generics($($impl_generics)*),
- @ty_generics($($ty_generics)*),
- @decl_generics($($decl_generics)*),
- @where($($whr)*),
- @fields_munch($field $($rest)*),
- @pinned($($pinned)*),
- @not_pinned($($not_pinned)*),
- @fields($($fields)*),
- @accum($($accum)* $fvis),
- @is_pinned($($is_pinned)?),
- @pinned_drop($($pinned_drop)?),
- );
- };
- (find_pinned_fields:
- @struct_attrs($($struct_attrs:tt)*),
- @vis($vis:vis),
- @name($name:ident),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @decl_generics($($decl_generics:tt)*),
- @where($($whr:tt)*),
- // Some other attribute, just put it into `$accum`.
- @fields_munch(#[$($attr:tt)*] $($rest:tt)*),
- @pinned($($pinned:tt)*),
- @not_pinned($($not_pinned:tt)*),
- @fields($($fields:tt)*),
- @accum($($accum:tt)*),
- @is_pinned($($is_pinned:ident)?),
- @pinned_drop($($pinned_drop:ident)?),
- ) => {
- $crate::__pin_data!(find_pinned_fields:
- @struct_attrs($($struct_attrs)*),
- @vis($vis),
- @name($name),
- @impl_generics($($impl_generics)*),
- @ty_generics($($ty_generics)*),
- @decl_generics($($decl_generics)*),
- @where($($whr)*),
- @fields_munch($($rest)*),
- @pinned($($pinned)*),
- @not_pinned($($not_pinned)*),
- @fields($($fields)*),
- @accum($($accum)* #[$($attr)*]),
- @is_pinned($($is_pinned)?),
- @pinned_drop($($pinned_drop)?),
- );
- };
- (find_pinned_fields:
- @struct_attrs($($struct_attrs:tt)*),
- @vis($vis:vis),
- @name($name:ident),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @decl_generics($($decl_generics:tt)*),
- @where($($whr:tt)*),
- // We reached the end of the fields, plus an optional additional comma, since we added one
- // before and the user is also allowed to put a trailing comma.
- @fields_munch($(,)?),
- @pinned($($pinned:tt)*),
- @not_pinned($($not_pinned:tt)*),
- @fields($($fields:tt)*),
- @accum(),
- @is_pinned(),
- @pinned_drop($($pinned_drop:ident)?),
- ) => {
- // Declare the struct with all fields in the correct order.
- $($struct_attrs)*
- $vis struct $name <$($decl_generics)*>
- where $($whr)*
- {
- $($fields)*
- }
-
- // We put the rest into this const item, because it then will not be accessible to anything
- // outside.
- const _: () = {
- // We declare this struct which will host all of the projection function for our type.
- // it will be invariant over all generic parameters which are inherited from the
- // struct.
- $vis struct __ThePinData<$($impl_generics)*>
- where $($whr)*
- {
- __phantom: ::core::marker::PhantomData<
- fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*>
- >,
- }
-
- impl<$($impl_generics)*> ::core::clone::Clone for __ThePinData<$($ty_generics)*>
- where $($whr)*
- {
- fn clone(&self) -> Self { *self }
- }
-
- impl<$($impl_generics)*> ::core::marker::Copy for __ThePinData<$($ty_generics)*>
- where $($whr)*
- {}
-
- // Make all projection functions.
- $crate::__pin_data!(make_pin_data:
- @pin_data(__ThePinData),
- @impl_generics($($impl_generics)*),
- @ty_generics($($ty_generics)*),
- @where($($whr)*),
- @pinned($($pinned)*),
- @not_pinned($($not_pinned)*),
- );
-
- // SAFETY: We have added the correct projection functions above to `__ThePinData` and
- // we also use the least restrictive generics possible.
- unsafe impl<$($impl_generics)*>
- $crate::init::__internal::HasPinData for $name<$($ty_generics)*>
- where $($whr)*
- {
- type PinData = __ThePinData<$($ty_generics)*>;
-
- unsafe fn __pin_data() -> Self::PinData {
- __ThePinData { __phantom: ::core::marker::PhantomData }
- }
- }
-
- // SAFETY: TODO.
- unsafe impl<$($impl_generics)*>
- $crate::init::__internal::PinData for __ThePinData<$($ty_generics)*>
- where $($whr)*
- {
- type Datee = $name<$($ty_generics)*>;
- }
-
- // This struct will be used for the unpin analysis. Since only structurally pinned
- // fields are relevant whether the struct should implement `Unpin`.
- #[allow(dead_code)]
- struct __Unpin <'__pin, $($impl_generics)*>
- where $($whr)*
- {
- __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
- __phantom: ::core::marker::PhantomData<
- fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*>
- >,
- // Only the pinned fields.
- $($pinned)*
- }
-
- #[doc(hidden)]
- impl<'__pin, $($impl_generics)*> ::core::marker::Unpin for $name<$($ty_generics)*>
- where
- __Unpin<'__pin, $($ty_generics)*>: ::core::marker::Unpin,
- $($whr)*
- {}
-
- // We need to disallow normal `Drop` implementation, the exact behavior depends on
- // whether `PinnedDrop` was specified as the parameter.
- $crate::__pin_data!(drop_prevention:
- @name($name),
- @impl_generics($($impl_generics)*),
- @ty_generics($($ty_generics)*),
- @where($($whr)*),
- @pinned_drop($($pinned_drop)?),
- );
- };
- };
- // When no `PinnedDrop` was specified, then we have to prevent implementing drop.
- (drop_prevention:
- @name($name:ident),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @where($($whr:tt)*),
- @pinned_drop(),
- ) => {
- // We prevent this by creating a trait that will be implemented for all types implementing
- // `Drop`. Additionally we will implement this trait for the struct leading to a conflict,
- // if it also implements `Drop`
- trait MustNotImplDrop {}
- #[expect(drop_bounds)]
- impl<T: ::core::ops::Drop> MustNotImplDrop for T {}
- impl<$($impl_generics)*> MustNotImplDrop for $name<$($ty_generics)*>
- where $($whr)* {}
- // We also take care to prevent users from writing a useless `PinnedDrop` implementation.
- // They might implement `PinnedDrop` correctly for the struct, but forget to give
- // `PinnedDrop` as the parameter to `#[pin_data]`.
- #[expect(non_camel_case_types)]
- trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
- impl<T: $crate::init::PinnedDrop>
- UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
- impl<$($impl_generics)*>
- UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for $name<$($ty_generics)*>
- where $($whr)* {}
- };
- // When `PinnedDrop` was specified we just implement `Drop` and delegate.
- (drop_prevention:
- @name($name:ident),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @where($($whr:tt)*),
- @pinned_drop(PinnedDrop),
- ) => {
- impl<$($impl_generics)*> ::core::ops::Drop for $name<$($ty_generics)*>
- where $($whr)*
- {
- fn drop(&mut self) {
- // SAFETY: Since this is a destructor, `self` will not move after this function
- // terminates, since it is inaccessible.
- let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) };
- // SAFETY: Since this is a drop function, we can create this token to call the
- // pinned destructor of this type.
- let token = unsafe { $crate::init::__internal::OnlyCallFromDrop::new() };
- $crate::init::PinnedDrop::drop(pinned, token);
- }
- }
- };
- // If some other parameter was specified, we emit a readable error.
- (drop_prevention:
- @name($name:ident),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @where($($whr:tt)*),
- @pinned_drop($($rest:tt)*),
- ) => {
- compile_error!(
- "Wrong parameters to `#[pin_data]`, expected nothing or `PinnedDrop`, got '{}'.",
- stringify!($($rest)*),
- );
- };
- (make_pin_data:
- @pin_data($pin_data:ident),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @where($($whr:tt)*),
- @pinned($($(#[$($p_attr:tt)*])* $pvis:vis $p_field:ident : $p_type:ty),* $(,)?),
- @not_pinned($($(#[$($attr:tt)*])* $fvis:vis $field:ident : $type:ty),* $(,)?),
- ) => {
- // For every field, we create a projection function according to its projection type. If a
- // field is structurally pinned, then it must be initialized via `PinInit`, if it is not
- // structurally pinned, then it can be initialized via `Init`.
- //
- // The functions are `unsafe` to prevent accidentally calling them.
- #[allow(dead_code)]
- #[expect(clippy::missing_safety_doc)]
- impl<$($impl_generics)*> $pin_data<$($ty_generics)*>
- where $($whr)*
- {
- $(
- $(#[$($p_attr)*])*
- $pvis unsafe fn $p_field<E>(
- self,
- slot: *mut $p_type,
- init: impl $crate::init::PinInit<$p_type, E>,
- ) -> ::core::result::Result<(), E> {
- // SAFETY: TODO.
- unsafe { $crate::init::PinInit::__pinned_init(init, slot) }
- }
- )*
- $(
- $(#[$($attr)*])*
- $fvis unsafe fn $field<E>(
- self,
- slot: *mut $type,
- init: impl $crate::init::Init<$type, E>,
- ) -> ::core::result::Result<(), E> {
- // SAFETY: TODO.
- unsafe { $crate::init::Init::__init(init, slot) }
- }
- )*
- }
- };
-}
-
-/// The internal init macro. Do not call manually!
-///
-/// This is called by the `{try_}{pin_}init!` macros with various inputs.
-///
-/// This macro has multiple internal call configurations, these are always the very first ident:
-/// - nothing: this is the base case and called by the `{try_}{pin_}init!` macros.
-/// - `with_update_parsed`: when the `..Zeroable::zeroed()` syntax has been handled.
-/// - `init_slot`: recursively creates the code that initializes all fields in `slot`.
-/// - `make_initializer`: recursively create the struct initializer that guarantees that every
-/// field has been initialized exactly once.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __init_internal {
- (
- @this($($this:ident)?),
- @typ($t:path),
- @fields($($fields:tt)*),
- @error($err:ty),
- // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
- // case.
- @data($data:ident, $($use_data:ident)?),
- // `HasPinData` or `HasInitData`.
- @has_data($has_data:ident, $get_data:ident),
- // `pin_init_from_closure` or `init_from_closure`.
- @construct_closure($construct_closure:ident),
- @munch_fields(),
- ) => {
- $crate::__init_internal!(with_update_parsed:
- @this($($this)?),
- @typ($t),
- @fields($($fields)*),
- @error($err),
- @data($data, $($use_data)?),
- @has_data($has_data, $get_data),
- @construct_closure($construct_closure),
- @zeroed(), // Nothing means default behavior.
- )
- };
- (
- @this($($this:ident)?),
- @typ($t:path),
- @fields($($fields:tt)*),
- @error($err:ty),
- // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
- // case.
- @data($data:ident, $($use_data:ident)?),
- // `HasPinData` or `HasInitData`.
- @has_data($has_data:ident, $get_data:ident),
- // `pin_init_from_closure` or `init_from_closure`.
- @construct_closure($construct_closure:ident),
- @munch_fields(..Zeroable::zeroed()),
- ) => {
- $crate::__init_internal!(with_update_parsed:
- @this($($this)?),
- @typ($t),
- @fields($($fields)*),
- @error($err),
- @data($data, $($use_data)?),
- @has_data($has_data, $get_data),
- @construct_closure($construct_closure),
- @zeroed(()), // `()` means zero all fields not mentioned.
- )
- };
- (
- @this($($this:ident)?),
- @typ($t:path),
- @fields($($fields:tt)*),
- @error($err:ty),
- // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
- // case.
- @data($data:ident, $($use_data:ident)?),
- // `HasPinData` or `HasInitData`.
- @has_data($has_data:ident, $get_data:ident),
- // `pin_init_from_closure` or `init_from_closure`.
- @construct_closure($construct_closure:ident),
- @munch_fields($ignore:tt $($rest:tt)*),
- ) => {
- $crate::__init_internal!(
- @this($($this)?),
- @typ($t),
- @fields($($fields)*),
- @error($err),
- @data($data, $($use_data)?),
- @has_data($has_data, $get_data),
- @construct_closure($construct_closure),
- @munch_fields($($rest)*),
- )
- };
- (with_update_parsed:
- @this($($this:ident)?),
- @typ($t:path),
- @fields($($fields:tt)*),
- @error($err:ty),
- // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
- // case.
- @data($data:ident, $($use_data:ident)?),
- // `HasPinData` or `HasInitData`.
- @has_data($has_data:ident, $get_data:ident),
- // `pin_init_from_closure` or `init_from_closure`.
- @construct_closure($construct_closure:ident),
- @zeroed($($init_zeroed:expr)?),
- ) => {{
- // We do not want to allow arbitrary returns, so we declare this type as the `Ok` return
- // type and shadow it later when we insert the arbitrary user code. That way there will be
- // no possibility of returning without `unsafe`.
- struct __InitOk;
- // Get the data about fields from the supplied type.
- //
- // SAFETY: TODO.
- let data = unsafe {
- use $crate::init::__internal::$has_data;
- // Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
- // information that is associated to already parsed fragments, so a path fragment
- // cannot be used in this position. Doing the retokenization results in valid rust
- // code.
- ::kernel::macros::paste!($t::$get_data())
- };
- // Ensure that `data` really is of type `$data` and help with type inference:
- let init = $crate::init::__internal::$data::make_closure::<_, __InitOk, $err>(
- data,
- move |slot| {
- {
- // Shadow the structure so it cannot be used to return early.
- struct __InitOk;
- // If `$init_zeroed` is present we should zero the slot now and not emit an
- // error when fields are missing (since they will be zeroed). We also have to
- // check that the type actually implements `Zeroable`.
- $({
- fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
- // Ensure that the struct is indeed `Zeroable`.
- assert_zeroable(slot);
- // SAFETY: The type implements `Zeroable` by the check above.
- unsafe { ::core::ptr::write_bytes(slot, 0, 1) };
- $init_zeroed // This will be `()` if set.
- })?
- // Create the `this` so it can be referenced by the user inside of the
- // expressions creating the individual fields.
- $(let $this = unsafe { ::core::ptr::NonNull::new_unchecked(slot) };)?
- // Initialize every field.
- $crate::__init_internal!(init_slot($($use_data)?):
- @data(data),
- @slot(slot),
- @guards(),
- @munch_fields($($fields)*,),
- );
- // We use unreachable code to ensure that all fields have been mentioned exactly
- // once, this struct initializer will still be type-checked and complain with a
- // very natural error message if a field is forgotten/mentioned more than once.
- #[allow(unreachable_code, clippy::diverging_sub_expression)]
- let _ = || {
- $crate::__init_internal!(make_initializer:
- @slot(slot),
- @type_name($t),
- @munch_fields($($fields)*,),
- @acc(),
- );
- };
- }
- Ok(__InitOk)
- }
- );
- let init = move |slot| -> ::core::result::Result<(), $err> {
- init(slot).map(|__InitOk| ())
- };
- // SAFETY: TODO.
- let init = unsafe { $crate::init::$construct_closure::<_, $err>(init) };
- init
- }};
- (init_slot($($use_data:ident)?):
- @data($data:ident),
- @slot($slot:ident),
- @guards($($guards:ident,)*),
- @munch_fields($(..Zeroable::zeroed())? $(,)?),
- ) => {
- // Endpoint of munching, no fields are left. If execution reaches this point, all fields
- // have been initialized. Therefore we can now dismiss the guards by forgetting them.
- $(::core::mem::forget($guards);)*
- };
- (init_slot($use_data:ident): // `use_data` is present, so we use the `data` to init fields.
- @data($data:ident),
- @slot($slot:ident),
- @guards($($guards:ident,)*),
- // In-place initialization syntax.
- @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
- ) => {
- let init = $val;
- // Call the initializer.
- //
- // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
- // return when an error/panic occurs.
- // We also use the `data` to require the correct trait (`Init` or `PinInit`) for `$field`.
- unsafe { $data.$field(::core::ptr::addr_of_mut!((*$slot).$field), init)? };
- // Create the drop guard:
- //
- // We rely on macro hygiene to make it impossible for users to access this local variable.
- // We use `paste!` to create new hygiene for `$field`.
- ::kernel::macros::paste! {
- // SAFETY: We forget the guard later when initialization has succeeded.
- let [< __ $field _guard >] = unsafe {
- $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
- };
-
- $crate::__init_internal!(init_slot($use_data):
- @data($data),
- @slot($slot),
- @guards([< __ $field _guard >], $($guards,)*),
- @munch_fields($($rest)*),
- );
- }
- };
- (init_slot(): // No `use_data`, so we use `Init::__init` directly.
- @data($data:ident),
- @slot($slot:ident),
- @guards($($guards:ident,)*),
- // In-place initialization syntax.
- @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
- ) => {
- let init = $val;
- // Call the initializer.
- //
- // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
- // return when an error/panic occurs.
- unsafe { $crate::init::Init::__init(init, ::core::ptr::addr_of_mut!((*$slot).$field))? };
- // Create the drop guard:
- //
- // We rely on macro hygiene to make it impossible for users to access this local variable.
- // We use `paste!` to create new hygiene for `$field`.
- ::kernel::macros::paste! {
- // SAFETY: We forget the guard later when initialization has succeeded.
- let [< __ $field _guard >] = unsafe {
- $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
- };
-
- $crate::__init_internal!(init_slot():
- @data($data),
- @slot($slot),
- @guards([< __ $field _guard >], $($guards,)*),
- @munch_fields($($rest)*),
- );
- }
- };
- (init_slot($($use_data:ident)?):
- @data($data:ident),
- @slot($slot:ident),
- @guards($($guards:ident,)*),
- // Init by-value.
- @munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
- ) => {
- {
- $(let $field = $val;)?
- // Initialize the field.
- //
- // SAFETY: The memory at `slot` is uninitialized.
- unsafe { ::core::ptr::write(::core::ptr::addr_of_mut!((*$slot).$field), $field) };
- }
- // Create the drop guard:
- //
- // We rely on macro hygiene to make it impossible for users to access this local variable.
- // We use `paste!` to create new hygiene for `$field`.
- ::kernel::macros::paste! {
- // SAFETY: We forget the guard later when initialization has succeeded.
- let [< __ $field _guard >] = unsafe {
- $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
- };
-
- $crate::__init_internal!(init_slot($($use_data)?):
- @data($data),
- @slot($slot),
- @guards([< __ $field _guard >], $($guards,)*),
- @munch_fields($($rest)*),
- );
- }
- };
- (make_initializer:
- @slot($slot:ident),
- @type_name($t:path),
- @munch_fields(..Zeroable::zeroed() $(,)?),
- @acc($($acc:tt)*),
- ) => {
- // Endpoint, nothing more to munch, create the initializer. Since the users specified
- // `..Zeroable::zeroed()`, the slot will already have been zeroed and all field that have
- // not been overwritten are thus zero and initialized. We still check that all fields are
- // actually accessible by using the struct update syntax ourselves.
- // We are inside of a closure that is never executed and thus we can abuse `slot` to
- // get the correct type inference here:
- #[allow(unused_assignments)]
- unsafe {
- let mut zeroed = ::core::mem::zeroed();
- // We have to use type inference here to make zeroed have the correct type. This does
- // not get executed, so it has no effect.
- ::core::ptr::write($slot, zeroed);
- zeroed = ::core::mem::zeroed();
- // Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
- // information that is associated to already parsed fragments, so a path fragment
- // cannot be used in this position. Doing the retokenization results in valid rust
- // code.
- ::kernel::macros::paste!(
- ::core::ptr::write($slot, $t {
- $($acc)*
- ..zeroed
- });
- );
- }
- };
- (make_initializer:
- @slot($slot:ident),
- @type_name($t:path),
- @munch_fields($(,)?),
- @acc($($acc:tt)*),
- ) => {
- // Endpoint, nothing more to munch, create the initializer.
- // Since we are in the closure that is never called, this will never get executed.
- // We abuse `slot` to get the correct type inference here:
- //
- // SAFETY: TODO.
- unsafe {
- // Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
- // information that is associated to already parsed fragments, so a path fragment
- // cannot be used in this position. Doing the retokenization results in valid rust
- // code.
- ::kernel::macros::paste!(
- ::core::ptr::write($slot, $t {
- $($acc)*
- });
- );
- }
- };
- (make_initializer:
- @slot($slot:ident),
- @type_name($t:path),
- @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
- @acc($($acc:tt)*),
- ) => {
- $crate::__init_internal!(make_initializer:
- @slot($slot),
- @type_name($t),
- @munch_fields($($rest)*),
- @acc($($acc)* $field: ::core::panic!(),),
- );
- };
- (make_initializer:
- @slot($slot:ident),
- @type_name($t:path),
- @munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
- @acc($($acc:tt)*),
- ) => {
- $crate::__init_internal!(make_initializer:
- @slot($slot),
- @type_name($t),
- @munch_fields($($rest)*),
- @acc($($acc)* $field: ::core::panic!(),),
- );
- };
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __derive_zeroable {
- (parse_input:
- @sig(
- $(#[$($struct_attr:tt)*])*
- $vis:vis struct $name:ident
- $(where $($whr:tt)*)?
- ),
- @impl_generics($($impl_generics:tt)*),
- @ty_generics($($ty_generics:tt)*),
- @body({
- $(
- $(#[$($field_attr:tt)*])*
- $field:ident : $field_ty:ty
- ),* $(,)?
- }),
- ) => {
- // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
- #[automatically_derived]
- unsafe impl<$($impl_generics)*> $crate::init::Zeroable for $name<$($ty_generics)*>
- where
- $($($whr)*)?
- {}
- const _: () = {
- fn assert_zeroable<T: ?::core::marker::Sized + $crate::init::Zeroable>() {}
- fn ensure_zeroable<$($impl_generics)*>()
- where $($($whr)*)?
- {
- $(assert_zeroable::<$field_ty>();)*
- }
- };
- };
-}
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 824da0e9738a..1604fb6a5b1b 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -40,6 +40,8 @@ pub fn info(args: fmt::Arguments<'_>) {
}
}
+use macros::kunit_tests;
+
/// Asserts that a boolean expression is `true` at runtime.
///
/// Public but hidden since it should only be used from generated tests.
@@ -161,3 +163,172 @@ macro_rules! kunit_assert_eq {
$crate::kunit_assert!($name, $file, $diff, $left == $right);
}};
}
+
+/// Represents an individual test case.
+///
+/// The [`kunit_unsafe_test_suite!`] macro expects a NULL-terminated list of valid test cases.
+/// Use [`kunit_case_null`] to generate such a delimiter.
+#[doc(hidden)]
+pub const fn kunit_case(
+ name: &'static kernel::str::CStr,
+ run_case: unsafe extern "C" fn(*mut kernel::bindings::kunit),
+) -> kernel::bindings::kunit_case {
+ kernel::bindings::kunit_case {
+ run_case: Some(run_case),
+ name: name.as_char_ptr(),
+ attr: kernel::bindings::kunit_attributes {
+ speed: kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL,
+ },
+ generate_params: None,
+ status: kernel::bindings::kunit_status_KUNIT_SUCCESS,
+ module_name: core::ptr::null_mut(),
+ log: core::ptr::null_mut(),
+ }
+}
+
+/// Represents the NULL test case delimiter.
+///
+/// The [`kunit_unsafe_test_suite!`] macro expects a NULL-terminated list of test cases. This
+/// function returns such a delimiter.
+#[doc(hidden)]
+pub const fn kunit_case_null() -> kernel::bindings::kunit_case {
+ kernel::bindings::kunit_case {
+ run_case: None,
+ name: core::ptr::null_mut(),
+ generate_params: None,
+ attr: kernel::bindings::kunit_attributes {
+ speed: kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL,
+ },
+ status: kernel::bindings::kunit_status_KUNIT_SUCCESS,
+ module_name: core::ptr::null_mut(),
+ log: core::ptr::null_mut(),
+ }
+}
+
+/// Registers a KUnit test suite.
+///
+/// # Safety
+///
+/// `test_cases` must be a NULL terminated array of valid test cases,
+/// whose lifetime is at least that of the test suite (i.e., static).
+///
+/// # Examples
+///
+/// ```ignore
+/// extern "C" fn test_fn(_test: *mut kernel::bindings::kunit) {
+/// let actual = 1 + 1;
+/// let expected = 2;
+/// assert_eq!(actual, expected);
+/// }
+///
+/// static mut KUNIT_TEST_CASES: [kernel::bindings::kunit_case; 2] = [
+/// kernel::kunit::kunit_case(kernel::c_str!("name"), test_fn),
+/// kernel::kunit::kunit_case_null(),
+/// ];
+/// kernel::kunit_unsafe_test_suite!(suite_name, KUNIT_TEST_CASES);
+/// ```
+#[doc(hidden)]
+#[macro_export]
+macro_rules! kunit_unsafe_test_suite {
+ ($name:ident, $test_cases:ident) => {
+ const _: () = {
+ const KUNIT_TEST_SUITE_NAME: [::kernel::ffi::c_char; 256] = {
+ let name_u8 = ::core::stringify!($name).as_bytes();
+ let mut ret = [0; 256];
+
+ if name_u8.len() > 255 {
+ panic!(concat!(
+ "The test suite name `",
+ ::core::stringify!($name),
+ "` exceeds the maximum length of 255 bytes."
+ ));
+ }
+
+ let mut i = 0;
+ while i < name_u8.len() {
+ ret[i] = name_u8[i] as ::kernel::ffi::c_char;
+ i += 1;
+ }
+
+ ret
+ };
+
+ static mut KUNIT_TEST_SUITE: ::kernel::bindings::kunit_suite =
+ ::kernel::bindings::kunit_suite {
+ name: KUNIT_TEST_SUITE_NAME,
+ #[allow(unused_unsafe)]
+ // SAFETY: `$test_cases` is passed in by the user, and
+ // (as documented) must be valid for the lifetime of
+ // the suite (i.e., static).
+ test_cases: unsafe {
+ ::core::ptr::addr_of_mut!($test_cases)
+ .cast::<::kernel::bindings::kunit_case>()
+ },
+ suite_init: None,
+ suite_exit: None,
+ init: None,
+ exit: None,
+ attr: ::kernel::bindings::kunit_attributes {
+ speed: ::kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL,
+ },
+ status_comment: [0; 256usize],
+ debugfs: ::core::ptr::null_mut(),
+ log: ::core::ptr::null_mut(),
+ suite_init_err: 0,
+ is_init: false,
+ };
+
+ #[used]
+ #[allow(unused_unsafe)]
+ #[cfg_attr(not(target_os = "macos"), link_section = ".kunit_test_suites")]
+ static mut KUNIT_TEST_SUITE_ENTRY: *const ::kernel::bindings::kunit_suite =
+ // SAFETY: `KUNIT_TEST_SUITE` is static.
+ unsafe { ::core::ptr::addr_of_mut!(KUNIT_TEST_SUITE) };
+ };
+ };
+}
+
+/// Returns whether we are currently running a KUnit test.
+///
+/// In some cases, you need to call test-only code from outside the test case, for example, to
+/// create a function mock. This function allows to change behavior depending on whether we are
+/// currently running a KUnit test or not.
+///
+/// # Examples
+///
+/// This example shows how a function can be mocked to return a well-known value while testing:
+///
+/// ```
+/// # use kernel::kunit::in_kunit_test;
+/// fn fn_mock_example(n: i32) -> i32 {
+/// if in_kunit_test() {
+/// return 100;
+/// }
+///
+/// n + 1
+/// }
+///
+/// let mock_res = fn_mock_example(5);
+/// assert_eq!(mock_res, 100);
+/// ```
+pub fn in_kunit_test() -> bool {
+ // SAFETY: `kunit_get_current_test()` is always safe to call (it has fallbacks for
+ // when KUnit is not enabled).
+ !unsafe { bindings::kunit_get_current_test() }.is_null()
+}
+
+#[kunit_tests(rust_kernel_kunit)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn rust_test_kunit_example_test() {
+ #![expect(clippy::eq_op)]
+ assert_eq!(1 + 1, 2);
+ }
+
+ #[test]
+ fn rust_test_kunit_in_kunit_test() {
+ assert!(in_kunit_test());
+ }
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 7697c60b2d1a..de07aadd1ff5 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -19,6 +19,8 @@
#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(unsize))]
#![feature(inline_const)]
#![feature(lint_reasons)]
+// Stable in Rust 1.82
+#![feature(raw_ref_op)]
// Stable in Rust 1.83
#![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_mut_refs)]
@@ -44,6 +46,7 @@ pub mod cred;
pub mod device;
pub mod device_id;
pub mod devres;
+pub mod dma;
pub mod driver;
pub mod error;
pub mod faux;
@@ -112,11 +115,11 @@ pub trait InPlaceModule: Sync + Send {
/// Creates an initialiser for the module.
///
/// It is called when the module is loaded.
- fn init(module: &'static ThisModule) -> impl init::PinInit<Self, error::Error>;
+ fn init(module: &'static ThisModule) -> impl pin_init::PinInit<Self, error::Error>;
}
impl<T: Module> InPlaceModule for T {
- fn init(module: &'static ThisModule) -> impl init::PinInit<Self, error::Error> {
+ fn init(module: &'static ThisModule) -> impl pin_init::PinInit<Self, error::Error> {
let initer = move |slot: *mut Self| {
let m = <Self as Module>::init(module)?;
@@ -126,7 +129,7 @@ impl<T: Module> InPlaceModule for T {
};
// SAFETY: On success, `initer` always fully initialises an instance of `Self`.
- unsafe { init::pin_init_from_closure(initer) }
+ unsafe { pin_init::pin_init_from_closure(initer) }
}
}
diff --git a/rust/kernel/list.rs b/rust/kernel/list.rs
index fb93330f4af4..a335c3b1ff5e 100644
--- a/rust/kernel/list.rs
+++ b/rust/kernel/list.rs
@@ -4,12 +4,12 @@
//! A linked list implementation.
-use crate::init::PinInit;
use crate::sync::ArcBorrow;
use crate::types::Opaque;
use core::iter::{DoubleEndedIterator, FusedIterator};
use core::marker::PhantomData;
use core::ptr;
+use pin_init::PinInit;
mod impl_list_item_mod;
pub use self::impl_list_item_mod::{
@@ -245,8 +245,20 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
self.first.is_null()
}
- /// Add the provided item to the back of the list.
- pub fn push_back(&mut self, item: ListArc<T, ID>) {
+ /// Inserts `item` before `next` in the cycle.
+ ///
+ /// Returns a pointer to the newly inserted element. Never changes `self.first` unless the list
+ /// is empty.
+ ///
+ /// # Safety
+ ///
+ /// * `next` must be an element in this list or null.
+ /// * if `next` is null, then the list must be empty.
+ unsafe fn insert_inner(
+ &mut self,
+ item: ListArc<T, ID>,
+ next: *mut ListLinksFields,
+ ) -> *mut ListLinksFields {
let raw_item = ListArc::into_raw(item);
// SAFETY:
// * We just got `raw_item` from a `ListArc`, so it's in an `Arc`.
@@ -259,16 +271,16 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
// SAFETY: We have not yet called `post_remove`, so `list_links` is still valid.
let item = unsafe { ListLinks::fields(list_links) };
- if self.first.is_null() {
- self.first = item;
+ // Check if the list is empty.
+ if next.is_null() {
// SAFETY: The caller just gave us ownership of these fields.
// INVARIANT: A linked list with one item should be cyclic.
unsafe {
(*item).next = item;
(*item).prev = item;
}
+ self.first = item;
} else {
- let next = self.first;
// SAFETY: By the type invariant, this pointer is valid or null. We just checked that
// it's not null, so it must be valid.
let prev = unsafe { (*next).prev };
@@ -282,45 +294,27 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
(*next).prev = item;
}
}
+
+ item
+ }
+
+ /// Add the provided item to the back of the list.
+ pub fn push_back(&mut self, item: ListArc<T, ID>) {
+ // SAFETY:
+ // * `self.first` is null or in the list.
+ // * `self.first` is only null if the list is empty.
+ unsafe { self.insert_inner(item, self.first) };
}
/// Add the provided item to the front of the list.
pub fn push_front(&mut self, item: ListArc<T, ID>) {
- let raw_item = ListArc::into_raw(item);
// SAFETY:
- // * We just got `raw_item` from a `ListArc`, so it's in an `Arc`.
- // * If this requirement is violated, then the previous caller of `prepare_to_insert`
- // violated the safety requirement that they can't give up ownership of the `ListArc`
- // until they call `post_remove`.
- // * We own the `ListArc`.
- // * Removing items] from this list is always done using `remove_internal_inner`, which
- // calls `post_remove` before giving up ownership.
- let list_links = unsafe { T::prepare_to_insert(raw_item) };
- // SAFETY: We have not yet called `post_remove`, so `list_links` is still valid.
- let item = unsafe { ListLinks::fields(list_links) };
+ // * `self.first` is null or in the list.
+ // * `self.first` is only null if the list is empty.
+ let new_elem = unsafe { self.insert_inner(item, self.first) };
- if self.first.is_null() {
- // SAFETY: The caller just gave us ownership of these fields.
- // INVARIANT: A linked list with one item should be cyclic.
- unsafe {
- (*item).next = item;
- (*item).prev = item;
- }
- } else {
- let next = self.first;
- // SAFETY: We just checked that `next` is non-null.
- let prev = unsafe { (*next).prev };
- // SAFETY: Pointers in a linked list are never dangling, and the caller just gave us
- // ownership of the fields on `item`.
- // INVARIANT: This correctly inserts `item` between `prev` and `next`.
- unsafe {
- (*item).next = next;
- (*item).prev = prev;
- (*prev).next = item;
- (*next).prev = item;
- }
- }
- self.first = item;
+ // INVARIANT: `new_elem` is in the list because we just inserted it.
+ self.first = new_elem;
}
/// Removes the last item from this list.
@@ -489,17 +483,21 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
other.first = ptr::null_mut();
}
- /// Returns a cursor to the first element of the list.
- ///
- /// If the list is empty, this returns `None`.
- pub fn cursor_front(&mut self) -> Option<Cursor<'_, T, ID>> {
- if self.first.is_null() {
- None
- } else {
- Some(Cursor {
- current: self.first,
- list: self,
- })
+ /// Returns a cursor that points before the first element of the list.
+ pub fn cursor_front(&mut self) -> Cursor<'_, T, ID> {
+ // INVARIANT: `self.first` is in this list.
+ Cursor {
+ next: self.first,
+ list: self,
+ }
+ }
+
+ /// Returns a cursor that points after the last element in the list.
+ pub fn cursor_back(&mut self) -> Cursor<'_, T, ID> {
+ // INVARIANT: `next` is allowed to be null.
+ Cursor {
+ next: core::ptr::null_mut(),
+ list: self,
}
}
@@ -579,69 +577,358 @@ impl<'a, T: ?Sized + ListItem<ID>, const ID: u64> Iterator for Iter<'a, T, ID> {
/// A cursor into a [`List`].
///
+/// A cursor always rests between two elements in the list. This means that a cursor has a previous
+/// and next element, but no current element. It also means that it's possible to have a cursor
+/// into an empty list.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::prelude::*;
+/// use kernel::list::{List, ListArc, ListLinks};
+///
+/// #[pin_data]
+/// struct ListItem {
+/// value: u32,
+/// #[pin]
+/// links: ListLinks,
+/// }
+///
+/// impl ListItem {
+/// fn new(value: u32) -> Result<ListArc<Self>> {
+/// ListArc::pin_init(try_pin_init!(Self {
+/// value,
+/// links <- ListLinks::new(),
+/// }), GFP_KERNEL)
+/// }
+/// }
+///
+/// kernel::list::impl_has_list_links! {
+/// impl HasListLinks<0> for ListItem { self.links }
+/// }
+/// kernel::list::impl_list_arc_safe! {
+/// impl ListArcSafe<0> for ListItem { untracked; }
+/// }
+/// kernel::list::impl_list_item! {
+/// impl ListItem<0> for ListItem { using ListLinks; }
+/// }
+///
+/// // Use a cursor to remove the first element with the given value.
+/// fn remove_first(list: &mut List<ListItem>, value: u32) -> Option<ListArc<ListItem>> {
+/// let mut cursor = list.cursor_front();
+/// while let Some(next) = cursor.peek_next() {
+/// if next.value == value {
+/// return Some(next.remove());
+/// }
+/// cursor.move_next();
+/// }
+/// None
+/// }
+///
+/// // Use a cursor to remove the last element with the given value.
+/// fn remove_last(list: &mut List<ListItem>, value: u32) -> Option<ListArc<ListItem>> {
+/// let mut cursor = list.cursor_back();
+/// while let Some(prev) = cursor.peek_prev() {
+/// if prev.value == value {
+/// return Some(prev.remove());
+/// }
+/// cursor.move_prev();
+/// }
+/// None
+/// }
+///
+/// // Use a cursor to remove all elements with the given value. The removed elements are moved to
+/// // a new list.
+/// fn remove_all(list: &mut List<ListItem>, value: u32) -> List<ListItem> {
+/// let mut out = List::new();
+/// let mut cursor = list.cursor_front();
+/// while let Some(next) = cursor.peek_next() {
+/// if next.value == value {
+/// out.push_back(next.remove());
+/// } else {
+/// cursor.move_next();
+/// }
+/// }
+/// out
+/// }
+///
+/// // Use a cursor to insert a value at a specific index. Returns an error if the index is out of
+/// // bounds.
+/// fn insert_at(list: &mut List<ListItem>, new: ListArc<ListItem>, idx: usize) -> Result {
+/// let mut cursor = list.cursor_front();
+/// for _ in 0..idx {
+/// if !cursor.move_next() {
+/// return Err(EINVAL);
+/// }
+/// }
+/// cursor.insert_next(new);
+/// Ok(())
+/// }
+///
+/// // Merge two sorted lists into a single sorted list.
+/// fn merge_sorted(list: &mut List<ListItem>, merge: List<ListItem>) {
+/// let mut cursor = list.cursor_front();
+/// for to_insert in merge {
+/// while let Some(next) = cursor.peek_next() {
+/// if to_insert.value < next.value {
+/// break;
+/// }
+/// cursor.move_next();
+/// }
+/// cursor.insert_prev(to_insert);
+/// }
+/// }
+///
+/// let mut list = List::new();
+/// list.push_back(ListItem::new(14)?);
+/// list.push_back(ListItem::new(12)?);
+/// list.push_back(ListItem::new(10)?);
+/// list.push_back(ListItem::new(12)?);
+/// list.push_back(ListItem::new(15)?);
+/// list.push_back(ListItem::new(14)?);
+/// assert_eq!(remove_all(&mut list, 12).iter().count(), 2);
+/// // [14, 10, 15, 14]
+/// assert!(remove_first(&mut list, 14).is_some());
+/// // [10, 15, 14]
+/// insert_at(&mut list, ListItem::new(12)?, 2)?;
+/// // [10, 15, 12, 14]
+/// assert!(remove_last(&mut list, 15).is_some());
+/// // [10, 12, 14]
+///
+/// let mut list2 = List::new();
+/// list2.push_back(ListItem::new(11)?);
+/// list2.push_back(ListItem::new(13)?);
+/// merge_sorted(&mut list, list2);
+///
+/// let mut items = list.into_iter();
+/// assert_eq!(items.next().unwrap().value, 10);
+/// assert_eq!(items.next().unwrap().value, 11);
+/// assert_eq!(items.next().unwrap().value, 12);
+/// assert_eq!(items.next().unwrap().value, 13);
+/// assert_eq!(items.next().unwrap().value, 14);
+/// assert!(items.next().is_none());
+/// # Result::<(), Error>::Ok(())
+/// ```
+///
/// # Invariants
///
-/// The `current` pointer points a value in `list`.
+/// The `next` pointer is null or points a value in `list`.
pub struct Cursor<'a, T: ?Sized + ListItem<ID>, const ID: u64 = 0> {
- current: *mut ListLinksFields,
list: &'a mut List<T, ID>,
+ /// Points at the element after this cursor, or null if the cursor is after the last element.
+ next: *mut ListLinksFields,
}
impl<'a, T: ?Sized + ListItem<ID>, const ID: u64> Cursor<'a, T, ID> {
- /// Access the current element of this cursor.
- pub fn current(&self) -> ArcBorrow<'_, T> {
- // SAFETY: The `current` pointer points a value in the list.
- let me = unsafe { T::view_value(ListLinks::from_fields(self.current)) };
- // SAFETY:
- // * All values in a list are stored in an `Arc`.
- // * The value cannot be removed from the list for the duration of the lifetime annotated
- // on the returned `ArcBorrow`, because removing it from the list would require mutable
- // access to the cursor or the list. However, the `ArcBorrow` holds an immutable borrow
- // on the cursor, which in turn holds a mutable borrow on the list, so any such
- // mutable access requires first releasing the immutable borrow on the cursor.
- // * Values in a list never have a `UniqueArc` reference, because the list has a `ListArc`
- // reference, and `UniqueArc` references must be unique.
- unsafe { ArcBorrow::from_raw(me) }
+ /// Returns a pointer to the element before the cursor.
+ ///
+ /// Returns null if there is no element before the cursor.
+ fn prev_ptr(&self) -> *mut ListLinksFields {
+ let mut next = self.next;
+ let first = self.list.first;
+ if next == first {
+ // We are before the first element.
+ return core::ptr::null_mut();
+ }
+
+ if next.is_null() {
+ // We are after the last element, so we need a pointer to the last element, which is
+ // the same as `(*first).prev`.
+ next = first;
+ }
+
+ // SAFETY: `next` can't be null, because then `first` must also be null, but in that case
+ // we would have exited at the `next == first` check. Thus, `next` is an element in the
+ // list, so we can access its `prev` pointer.
+ unsafe { (*next).prev }
+ }
+
+ /// Access the element after this cursor.
+ pub fn peek_next(&mut self) -> Option<CursorPeek<'_, 'a, T, true, ID>> {
+ if self.next.is_null() {
+ return None;
+ }
+
+ // INVARIANT:
+ // * We just checked that `self.next` is non-null, so it must be in `self.list`.
+ // * `ptr` is equal to `self.next`.
+ Some(CursorPeek {
+ ptr: self.next,
+ cursor: self,
+ })
+ }
+
+ /// Access the element before this cursor.
+ pub fn peek_prev(&mut self) -> Option<CursorPeek<'_, 'a, T, false, ID>> {
+ let prev = self.prev_ptr();
+
+ if prev.is_null() {
+ return None;
+ }
+
+ // INVARIANT:
+ // * We just checked that `prev` is non-null, so it must be in `self.list`.
+ // * `self.prev_ptr()` never returns `self.next`.
+ Some(CursorPeek {
+ ptr: prev,
+ cursor: self,
+ })
}
- /// Move the cursor to the next element.
- pub fn next(self) -> Option<Cursor<'a, T, ID>> {
- // SAFETY: The `current` field is always in a list.
- let next = unsafe { (*self.current).next };
+ /// Move the cursor one element forward.
+ ///
+ /// If the cursor is after the last element, then this call does nothing. This call returns
+ /// `true` if the cursor's position was changed.
+ pub fn move_next(&mut self) -> bool {
+ if self.next.is_null() {
+ return false;
+ }
+
+ // SAFETY: `self.next` is an element in the list and we borrow the list mutably, so we can
+ // access the `next` field.
+ let mut next = unsafe { (*self.next).next };
if next == self.list.first {
- None
- } else {
- // INVARIANT: Since `self.current` is in the `list`, its `next` pointer is also in the
- // `list`.
- Some(Cursor {
- current: next,
- list: self.list,
- })
+ next = core::ptr::null_mut();
}
+
+ // INVARIANT: `next` is either null or the next element after an element in the list.
+ self.next = next;
+ true
}
- /// Move the cursor to the previous element.
- pub fn prev(self) -> Option<Cursor<'a, T, ID>> {
- // SAFETY: The `current` field is always in a list.
- let prev = unsafe { (*self.current).prev };
+ /// Move the cursor one element backwards.
+ ///
+ /// If the cursor is before the first element, then this call does nothing. This call returns
+ /// `true` if the cursor's position was changed.
+ pub fn move_prev(&mut self) -> bool {
+ if self.next == self.list.first {
+ return false;
+ }
- if self.current == self.list.first {
- None
+ // INVARIANT: `prev_ptr()` always returns a pointer that is null or in the list.
+ self.next = self.prev_ptr();
+ true
+ }
+
+ /// Inserts an element where the cursor is pointing and get a pointer to the new element.
+ fn insert_inner(&mut self, item: ListArc<T, ID>) -> *mut ListLinksFields {
+ let ptr = if self.next.is_null() {
+ self.list.first
} else {
- // INVARIANT: Since `self.current` is in the `list`, its `prev` pointer is also in the
- // `list`.
- Some(Cursor {
- current: prev,
- list: self.list,
- })
+ self.next
+ };
+ // SAFETY:
+ // * `ptr` is an element in the list or null.
+ // * if `ptr` is null, then `self.list.first` is null so the list is empty.
+ let item = unsafe { self.list.insert_inner(item, ptr) };
+ if self.next == self.list.first {
+ // INVARIANT: We just inserted `item`, so it's a member of list.
+ self.list.first = item;
}
+ item
}
- /// Remove the current element from the list.
+ /// Insert an element at this cursor's location.
+ pub fn insert(mut self, item: ListArc<T, ID>) {
+ // This is identical to `insert_prev`, but consumes the cursor. This is helpful because it
+ // reduces confusion when the last operation on the cursor is an insertion; in that case,
+ // you just want to insert the element at the cursor, and it is confusing that the call
+ // involves the word prev or next.
+ self.insert_inner(item);
+ }
+
+ /// Inserts an element after this cursor.
+ ///
+ /// After insertion, the new element will be after the cursor.
+ pub fn insert_next(&mut self, item: ListArc<T, ID>) {
+ self.next = self.insert_inner(item);
+ }
+
+ /// Inserts an element before this cursor.
+ ///
+ /// After insertion, the new element will be before the cursor.
+ pub fn insert_prev(&mut self, item: ListArc<T, ID>) {
+ self.insert_inner(item);
+ }
+
+ /// Remove the next element from the list.
+ pub fn remove_next(&mut self) -> Option<ListArc<T, ID>> {
+ self.peek_next().map(|v| v.remove())
+ }
+
+ /// Remove the previous element from the list.
+ pub fn remove_prev(&mut self) -> Option<ListArc<T, ID>> {
+ self.peek_prev().map(|v| v.remove())
+ }
+}
+
+/// References the element in the list next to the cursor.
+///
+/// # Invariants
+///
+/// * `ptr` is an element in `self.cursor.list`.
+/// * `ISNEXT == (self.ptr == self.cursor.next)`.
+pub struct CursorPeek<'a, 'b, T: ?Sized + ListItem<ID>, const ISNEXT: bool, const ID: u64> {
+ cursor: &'a mut Cursor<'b, T, ID>,
+ ptr: *mut ListLinksFields,
+}
+
+impl<'a, 'b, T: ?Sized + ListItem<ID>, const ISNEXT: bool, const ID: u64>
+ CursorPeek<'a, 'b, T, ISNEXT, ID>
+{
+ /// Remove the element from the list.
pub fn remove(self) -> ListArc<T, ID> {
- // SAFETY: The `current` pointer always points at a member of the list.
- unsafe { self.list.remove_internal(self.current) }
+ if ISNEXT {
+ self.cursor.move_next();
+ }
+
+ // INVARIANT: `self.ptr` is not equal to `self.cursor.next` due to the above `move_next`
+ // call.
+ // SAFETY: By the type invariants of `Self`, `next` is not null, so `next` is an element of
+ // `self.cursor.list` by the type invariants of `Cursor`.
+ unsafe { self.cursor.list.remove_internal(self.ptr) }
+ }
+
+ /// Access this value as an [`ArcBorrow`].
+ pub fn arc(&self) -> ArcBorrow<'_, T> {
+ // SAFETY: `self.ptr` points at an element in `self.cursor.list`.
+ let me = unsafe { T::view_value(ListLinks::from_fields(self.ptr)) };
+ // SAFETY:
+ // * All values in a list are stored in an `Arc`.
+ // * The value cannot be removed from the list for the duration of the lifetime annotated
+ // on the returned `ArcBorrow`, because removing it from the list would require mutable
+ // access to the `CursorPeek`, the `Cursor` or the `List`. However, the `ArcBorrow` holds
+ // an immutable borrow on the `CursorPeek`, which in turn holds a mutable borrow on the
+ // `Cursor`, which in turn holds a mutable borrow on the `List`, so any such mutable
+ // access requires first releasing the immutable borrow on the `CursorPeek`.
+ // * Values in a list never have a `UniqueArc` reference, because the list has a `ListArc`
+ // reference, and `UniqueArc` references must be unique.
+ unsafe { ArcBorrow::from_raw(me) }
+ }
+}
+
+impl<'a, 'b, T: ?Sized + ListItem<ID>, const ISNEXT: bool, const ID: u64> core::ops::Deref
+ for CursorPeek<'a, 'b, T, ISNEXT, ID>
+{
+ // If you change the `ptr` field to have type `ArcBorrow<'a, T>`, it might seem like you could
+ // get rid of the `CursorPeek::arc` method and change the deref target to `ArcBorrow<'a, T>`.
+ // However, that doesn't work because 'a is too long. You could obtain an `ArcBorrow<'a, T>`
+ // and then call `CursorPeek::remove` without giving up the `ArcBorrow<'a, T>`, which would be
+ // unsound.
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ // SAFETY: `self.ptr` points at an element in `self.cursor.list`.
+ let me = unsafe { T::view_value(ListLinks::from_fields(self.ptr)) };
+
+ // SAFETY: The value cannot be removed from the list for the duration of the lifetime
+ // annotated on the returned `&T`, because removing it from the list would require mutable
+ // access to the `CursorPeek`, the `Cursor` or the `List`. However, the `&T` holds an
+ // immutable borrow on the `CursorPeek`, which in turn holds a mutable borrow on the
+ // `Cursor`, which in turn holds a mutable borrow on the `List`, so any such mutable access
+ // requires first releasing the immutable borrow on the `CursorPeek`.
+ unsafe { &*me }
}
}
diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index bb654a28dab3..a59469c785e3 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -790,7 +790,7 @@ impl DeviceMask {
/// DeviceId::new_with_driver::<PhySample>()
/// ],
/// name: "rust_sample_phy",
-/// author: "Rust for Linux Contributors",
+/// authors: ["Rust for Linux Contributors"],
/// description: "Rust sample PHYs driver",
/// license: "GPL",
/// }
@@ -819,7 +819,7 @@ impl DeviceMask {
/// module! {
/// type: Module,
/// name: "rust_sample_phy",
-/// author: "Rust for Linux Contributors",
+/// authors: ["Rust for Linux Contributors"],
/// description: "Rust sample PHYs driver",
/// license: "GPL",
/// }
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 4c98b5b9aa1e..f7b2743828ae 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -103,7 +103,7 @@ impl<T: Driver + 'static> Adapter<T> {
/// kernel::module_pci_driver! {
/// type: MyDriver,
/// name: "Module name",
-/// author: "Author name",
+/// authors: ["Author name"],
/// description: "Description",
/// license: "GPL v2",
/// }
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index 50e6b0421813..1297f5292ba9 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -101,7 +101,7 @@ impl<T: Driver + 'static> driver::Adapter for Adapter<T> {
/// kernel::module_platform_driver! {
/// type: MyDriver,
/// name: "Module name",
-/// author: "Author name",
+/// authors: ["Author name"],
/// description: "Description",
/// license: "GPL v2",
/// }
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index dde2e0649790..baa774a351ce 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -17,7 +17,9 @@ pub use core::pin::Pin;
pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec, Vec};
#[doc(no_inline)]
-pub use macros::{module, pin_data, pinned_drop, vtable, Zeroable};
+pub use macros::{export, module, vtable};
+
+pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, Init, PinInit, Zeroable};
pub use super::{build_assert, build_error};
@@ -28,7 +30,7 @@ pub use super::fmt;
pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info, dev_notice, dev_warn};
pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
-pub use super::{init, pin_init, try_init, try_pin_init};
+pub use super::{try_init, try_pin_init};
pub use super::static_assert;
@@ -36,6 +38,6 @@ pub use super::error::{code::*, Error, Result};
pub use super::{str::CStr, ThisModule};
-pub use super::init::{InPlaceInit, InPlaceWrite, Init, PinInit};
+pub use super::init::InPlaceInit;
pub use super::current;
diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
index b19ee490be58..cf4714242e14 100644
--- a/rust/kernel/print.rs
+++ b/rust/kernel/print.rs
@@ -6,16 +6,16 @@
//!
//! Reference: <https://docs.kernel.org/core-api/printk-basics.html>
-use core::{
+use crate::{
ffi::{c_char, c_void},
- fmt,
+ prelude::*,
+ str::RawFormatter,
};
-
-use crate::str::RawFormatter;
+use core::fmt;
// Called from `vsprintf` with format specifier `%pA`.
#[expect(clippy::missing_safety_doc)]
-#[no_mangle]
+#[export]
unsafe extern "C" fn rust_fmt_argument(
buf: *mut c_char,
end: *mut c_char,
diff --git a/rust/kernel/rbtree.rs b/rust/kernel/rbtree.rs
index 0d1e75810664..5246b2c8a4ff 100644
--- a/rust/kernel/rbtree.rs
+++ b/rust/kernel/rbtree.rs
@@ -886,7 +886,7 @@ impl<'a, K, V> Cursor<'a, K, V> {
/// # Safety
///
/// - `node` must be a valid pointer to a node in an [`RBTree`].
- /// - The caller has immutable access to `node` for the duration of 'b.
+ /// - The caller has immutable access to `node` for the duration of `'b`.
unsafe fn to_key_value<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, &'b V) {
// SAFETY: the caller guarantees that `node` is a valid pointer in an `RBTree`.
let (k, v) = unsafe { Self::to_key_value_raw(node) };
@@ -897,7 +897,7 @@ impl<'a, K, V> Cursor<'a, K, V> {
/// # Safety
///
/// - `node` must be a valid pointer to a node in an [`RBTree`].
- /// - The caller has mutable access to `node` for the duration of 'b.
+ /// - The caller has mutable access to `node` for the duration of `'b`.
unsafe fn to_key_value_mut<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, &'b mut V) {
// SAFETY: the caller guarantees that `node` is a valid pointer in an `RBTree`.
let (k, v) = unsafe { Self::to_key_value_raw(node) };
@@ -908,7 +908,7 @@ impl<'a, K, V> Cursor<'a, K, V> {
/// # Safety
///
/// - `node` must be a valid pointer to a node in an [`RBTree`].
- /// - The caller has immutable access to the key for the duration of 'b.
+ /// - The caller has immutable access to the key for the duration of `'b`.
unsafe fn to_key_value_raw<'b>(node: NonNull<bindings::rb_node>) -> (&'b K, *mut V) {
// SAFETY: By the type invariant of `Self`, all non-null `rb_node` pointers stored in `self`
// point to the links field of `Node<K, V>` objects.
@@ -1168,12 +1168,12 @@ impl<'a, K, V> RawVacantEntry<'a, K, V> {
fn insert(self, node: RBTreeNode<K, V>) -> &'a mut V {
let node = KBox::into_raw(node.node);
- // SAFETY: `node` is valid at least until we call `Box::from_raw`, which only happens when
+ // SAFETY: `node` is valid at least until we call `KBox::from_raw`, which only happens when
// the node is removed or replaced.
let node_links = unsafe { addr_of_mut!((*node).links) };
// INVARIANT: We are linking in a new node, which is valid. It remains valid because we
- // "forgot" it with `Box::into_raw`.
+ // "forgot" it with `KBox::into_raw`.
// SAFETY: The type invariants of `RawVacantEntry` are exactly the safety requirements of `rb_link_node`.
unsafe { bindings::rb_link_node(node_links, self.parent, self.child_field_of_parent) };
@@ -1259,7 +1259,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
fn replace(self, node: RBTreeNode<K, V>) -> RBTreeNode<K, V> {
let node = KBox::into_raw(node.node);
- // SAFETY: `node` is valid at least until we call `Box::from_raw`, which only happens when
+ // SAFETY: `node` is valid at least until we call `KBox::from_raw`, which only happens when
// the node is removed or replaced.
let new_node_links = unsafe { addr_of_mut!((*node).links) };
diff --git a/rust/kernel/security.rs b/rust/kernel/security.rs
index 25d2b1ac3833..0c63e9e7e564 100644
--- a/rust/kernel/security.rs
+++ b/rust/kernel/security.rs
@@ -16,13 +16,14 @@ use crate::{
/// # Invariants
///
/// The `ctx` field corresponds to a valid security context as returned by a successful call to
-/// `security_secid_to_secctx`, that has not yet been destroyed by `security_release_secctx`.
+/// `security_secid_to_secctx`, that has not yet been released by `security_release_secctx`.
pub struct SecurityCtx {
ctx: bindings::lsm_context,
}
impl SecurityCtx {
/// Get the security context given its id.
+ #[inline]
pub fn from_secid(secid: u32) -> Result<Self> {
// SAFETY: `struct lsm_context` can be initialized to all zeros.
let mut ctx: bindings::lsm_context = unsafe { core::mem::zeroed() };
@@ -35,16 +36,19 @@ impl SecurityCtx {
}
/// Returns whether the security context is empty.
+ #[inline]
pub fn is_empty(&self) -> bool {
self.ctx.len == 0
}
/// Returns the length of this security context.
+ #[inline]
pub fn len(&self) -> usize {
self.ctx.len as usize
}
/// Returns the bytes for this security context.
+ #[inline]
pub fn as_bytes(&self) -> &[u8] {
let ptr = self.ctx.context;
if ptr.is_null() {
@@ -61,10 +65,10 @@ impl SecurityCtx {
}
impl Drop for SecurityCtx {
+ #[inline]
fn drop(&mut self) {
- // SAFETY: By the invariant of `Self`, this frees a context that came from a successful
- // call to `security_secid_to_secctx` and has not yet been destroyed by
- // `security_release_secctx`.
+ // SAFETY: By the invariant of `Self`, this releases an lsm context that came from a
+ // successful call to `security_secid_to_secctx` and has not yet been released.
unsafe { bindings::security_release_secctx(&mut self.ctx) };
}
}
diff --git a/rust/kernel/seq_file.rs b/rust/kernel/seq_file.rs
index 04947c672979..7a9403eb6e5b 100644
--- a/rust/kernel/seq_file.rs
+++ b/rust/kernel/seq_file.rs
@@ -18,7 +18,7 @@ impl SeqFile {
///
/// # Safety
///
- /// The caller must ensure that for the duration of 'a the following is satisfied:
+ /// The caller must ensure that for the duration of `'a` the following is satisfied:
/// * The pointer points at a valid `struct seq_file`.
/// * The `struct seq_file` is not accessed from any other thread.
pub unsafe fn from_raw<'a>(ptr: *mut bindings::seq_file) -> &'a SeqFile {
@@ -30,6 +30,7 @@ impl SeqFile {
}
/// Used by the [`seq_print`] macro.
+ #[inline]
pub fn call_printf(&self, args: core::fmt::Arguments<'_>) {
// SAFETY: Passing a void pointer to `Arguments` is valid for `%pA`.
unsafe {
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index 28e2201604d6..878111cb77bc 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -31,6 +31,23 @@ impl BStr {
// SAFETY: `BStr` is transparent to `[u8]`.
unsafe { &*(bytes as *const [u8] as *const BStr) }
}
+
+ /// Strip a prefix from `self`. Delegates to [`slice::strip_prefix`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use kernel::b_str;
+ /// assert_eq!(Some(b_str!("bar")), b_str!("foobar").strip_prefix(b_str!("foo")));
+ /// assert_eq!(None, b_str!("foobar").strip_prefix(b_str!("bar")));
+ /// assert_eq!(Some(b_str!("foobar")), b_str!("foobar").strip_prefix(b_str!("")));
+ /// assert_eq!(Some(b_str!("")), b_str!("foobar").strip_prefix(b_str!("foobar")));
+ /// ```
+ pub fn strip_prefix(&self, pattern: impl AsRef<Self>) -> Option<&BStr> {
+ self.deref()
+ .strip_prefix(pattern.as_ref().deref())
+ .map(Self::from_bytes)
+ }
}
impl fmt::Display for BStr {
@@ -108,6 +125,35 @@ impl Deref for BStr {
}
}
+impl PartialEq for BStr {
+ fn eq(&self, other: &Self) -> bool {
+ self.deref().eq(other.deref())
+ }
+}
+
+impl<Idx> Index<Idx> for BStr
+where
+ [u8]: Index<Idx, Output = [u8]>,
+{
+ type Output = Self;
+
+ fn index(&self, index: Idx) -> &Self::Output {
+ BStr::from_bytes(&self.0[index])
+ }
+}
+
+impl AsRef<BStr> for [u8] {
+ fn as_ref(&self) -> &BStr {
+ BStr::from_bytes(self)
+ }
+}
+
+impl AsRef<BStr> for BStr {
+ fn as_ref(&self) -> &BStr {
+ self
+ }
+}
+
/// Creates a new [`BStr`] from a string literal.
///
/// `b_str!` converts the supplied string literal to byte string, so non-ASCII
diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
index 16eab9138b2b..36a719015583 100644
--- a/rust/kernel/sync.rs
+++ b/rust/kernel/sync.rs
@@ -5,7 +5,9 @@
//! This module contains the kernel APIs related to synchronisation that have been ported or
//! wrapped for usage by Rust code in the kernel.
+use crate::prelude::*;
use crate::types::Opaque;
+use pin_init;
mod arc;
mod condvar;
@@ -23,15 +25,65 @@ pub use locked_by::LockedBy;
/// Represents a lockdep class. It's a wrapper around C's `lock_class_key`.
#[repr(transparent)]
-pub struct LockClassKey(Opaque<bindings::lock_class_key>);
+#[pin_data(PinnedDrop)]
+pub struct LockClassKey {
+ #[pin]
+ inner: Opaque<bindings::lock_class_key>,
+}
// SAFETY: `bindings::lock_class_key` is designed to be used concurrently from multiple threads and
// provides its own synchronization.
unsafe impl Sync for LockClassKey {}
impl LockClassKey {
+ /// Initializes a dynamically allocated lock class key. In the common case of using a
+ /// statically allocated lock class key, the static_lock_class! macro should be used instead.
+ ///
+ /// # Example
+ /// ```
+ /// # use kernel::c_str;
+ /// # use kernel::alloc::KBox;
+ /// # use kernel::types::ForeignOwnable;
+ /// # use kernel::sync::{LockClassKey, SpinLock};
+ /// # use pin_init::stack_pin_init;
+ ///
+ /// let key = KBox::pin_init(LockClassKey::new_dynamic(), GFP_KERNEL)?;
+ /// let key_ptr = key.into_foreign();
+ ///
+ /// {
+ /// stack_pin_init!(let num: SpinLock<u32> = SpinLock::new(
+ /// 0,
+ /// c_str!("my_spinlock"),
+ /// // SAFETY: `key_ptr` is returned by the above `into_foreign()`, whose
+ /// // `from_foreign()` has not yet been called.
+ /// unsafe { <Pin<KBox<LockClassKey>> as ForeignOwnable>::borrow(key_ptr) }
+ /// ));
+ /// }
+ ///
+ /// // SAFETY: We dropped `num`, the only use of the key, so the result of the previous
+ /// // `borrow` has also been dropped. Thus, it's safe to use from_foreign.
+ /// unsafe { drop(<Pin<KBox<LockClassKey>> as ForeignOwnable>::from_foreign(key_ptr)) };
+ ///
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn new_dynamic() -> impl PinInit<Self> {
+ pin_init!(Self {
+ // SAFETY: lockdep_register_key expects an uninitialized block of memory
+ inner <- Opaque::ffi_init(|slot| unsafe { bindings::lockdep_register_key(slot) })
+ })
+ }
+
pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key {
- self.0.get()
+ self.inner.get()
+ }
+}
+
+#[pinned_drop]
+impl PinnedDrop for LockClassKey {
+ fn drop(self: Pin<&mut Self>) {
+ // SAFETY: self.as_ptr was registered with lockdep and self is pinned, so the address
+ // hasn't changed. Thus, it's safe to pass to unregister.
+ unsafe { bindings::lockdep_unregister_key(self.as_ptr()) }
}
}
@@ -44,7 +96,7 @@ macro_rules! static_lock_class {
// SAFETY: lockdep expects uninitialized memory when it's handed a statically allocated
// lock_class_key
unsafe { ::core::mem::MaybeUninit::uninit().assume_init() };
- &CLASS
+ $crate::prelude::Pin::static_ref(&CLASS)
}};
}
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index 3cefda7a4372..8484c814609a 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -19,7 +19,7 @@
use crate::{
alloc::{AllocError, Flags, KBox},
bindings,
- init::{self, InPlaceInit, Init, PinInit},
+ init::InPlaceInit,
try_init,
types::{ForeignOwnable, Opaque},
};
@@ -32,7 +32,7 @@ use core::{
pin::Pin,
ptr::NonNull,
};
-use macros::pin_data;
+use pin_init::{self, pin_data, InPlaceWrite, Init, PinInit};
mod std_vendor;
@@ -202,6 +202,26 @@ unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}
// the reference count reaches zero and `T` is dropped.
unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
+impl<T> InPlaceInit<T> for Arc<T> {
+ type PinnedSelf = Self;
+
+ #[inline]
+ fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
+ where
+ E: From<AllocError>,
+ {
+ UniqueArc::try_pin_init(init, flags).map(|u| u.into())
+ }
+
+ #[inline]
+ fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
+ where
+ E: From<AllocError>,
+ {
+ UniqueArc::try_init(init, flags).map(|u| u.into())
+ }
+}
+
impl<T> Arc<T> {
/// Constructs a new reference counted instance of `T`.
pub fn new(contents: T, flags: Flags) -> Result<Self, AllocError> {
@@ -246,6 +266,15 @@ impl<T: ?Sized> Arc<T> {
unsafe { core::ptr::addr_of!((*ptr).data) }
}
+ /// Return a raw pointer to the data in this arc.
+ pub fn as_ptr(this: &Self) -> *const T {
+ let ptr = this.ptr.as_ptr();
+
+ // SAFETY: As `ptr` points to a valid allocation of type `ArcInner`,
+ // field projection to `data`is within bounds of the allocation.
+ unsafe { core::ptr::addr_of!((*ptr).data) }
+ }
+
/// Recreates an [`Arc`] instance previously deconstructed via [`Arc::into_raw`].
///
/// # Safety
@@ -539,11 +568,11 @@ impl<T: ?Sized> ArcBorrow<'_, T> {
}
/// Creates an [`ArcBorrow`] to an [`Arc`] that has previously been deconstructed with
- /// [`Arc::into_raw`].
+ /// [`Arc::into_raw`] or [`Arc::as_ptr`].
///
/// # Safety
///
- /// * The provided pointer must originate from a call to [`Arc::into_raw`].
+ /// * The provided pointer must originate from a call to [`Arc::into_raw`] or [`Arc::as_ptr`].
/// * For the duration of the lifetime annotated on this `ArcBorrow`, the reference count must
/// not hit zero.
/// * For the duration of the lifetime annotated on this `ArcBorrow`, there must not be a
@@ -659,6 +688,48 @@ pub struct UniqueArc<T: ?Sized> {
inner: Arc<T>,
}
+impl<T> InPlaceInit<T> for UniqueArc<T> {
+ type PinnedSelf = Pin<Self>;
+
+ #[inline]
+ fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
+ where
+ E: From<AllocError>,
+ {
+ UniqueArc::new_uninit(flags)?.write_pin_init(init)
+ }
+
+ #[inline]
+ fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
+ where
+ E: From<AllocError>,
+ {
+ UniqueArc::new_uninit(flags)?.write_init(init)
+ }
+}
+
+impl<T> InPlaceWrite<T> for UniqueArc<MaybeUninit<T>> {
+ type Initialized = UniqueArc<T>;
+
+ fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> {
+ let slot = self.as_mut_ptr();
+ // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
+ // slot is valid.
+ unsafe { init.__init(slot)? };
+ // SAFETY: All fields have been initialized.
+ Ok(unsafe { self.assume_init() })
+ }
+
+ fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> {
+ let slot = self.as_mut_ptr();
+ // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
+ // slot is valid and will not be moved, because we pin it later.
+ unsafe { init.__pinned_init(slot)? };
+ // SAFETY: All fields have been initialized.
+ Ok(unsafe { self.assume_init() }.into())
+ }
+}
+
impl<T> UniqueArc<T> {
/// Tries to allocate a new [`UniqueArc`] instance.
pub fn new(value: T, flags: Flags) -> Result<Self, AllocError> {
@@ -675,7 +746,7 @@ impl<T> UniqueArc<T> {
try_init!(ArcInner {
// SAFETY: There are no safety requirements for this FFI call.
refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) }),
- data <- init::uninit::<T, AllocError>(),
+ data <- pin_init::uninit::<T, AllocError>(),
}? AllocError),
flags,
)?;
diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index 7df565038d7d..caebf03f553b 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -8,16 +8,15 @@
use super::{lock::Backend, lock::Guard, LockClassKey};
use crate::{
ffi::{c_int, c_long},
- init::PinInit,
- pin_init,
str::CStr,
- task::{MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE},
+ task::{
+ MAX_SCHEDULE_TIMEOUT, TASK_FREEZABLE, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE,
+ },
time::Jiffies,
types::Opaque,
};
-use core::marker::PhantomPinned;
-use core::ptr;
-use macros::pin_data;
+use core::{marker::PhantomPinned, pin::Pin, ptr};
+use pin_init::{pin_data, pin_init, PinInit};
/// Creates a [`CondVar`] initialiser with the given name and a newly-created lock class.
#[macro_export]
@@ -37,7 +36,7 @@ pub use new_condvar;
/// spuriously.
///
/// Instances of [`CondVar`] need a lock class and to be pinned. The recommended way to create such
-/// instances is with the [`pin_init`](crate::pin_init) and [`new_condvar`] macros.
+/// instances is with the [`pin_init`](crate::pin_init!) and [`new_condvar`] macros.
///
/// # Examples
///
@@ -101,7 +100,7 @@ unsafe impl Sync for CondVar {}
impl CondVar {
/// Constructs a new condvar initialiser.
- pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
+ pub fn new(name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self> {
pin_init!(Self {
_pin: PhantomPinned,
// SAFETY: `slot` is valid while the closure is called and both `name` and `key` have
@@ -159,6 +158,25 @@ impl CondVar {
crate::current!().signal_pending()
}
+ /// Releases the lock and waits for a notification in interruptible and freezable mode.
+ ///
+ /// The process is allowed to be frozen during this sleep. No lock should be held when calling
+ /// this function, and there is a lockdep assertion for this. Freezing a task that holds a lock
+ /// can trivially deadlock vs another task that needs that lock to complete before it too can
+ /// hit freezable.
+ #[must_use = "wait_interruptible_freezable returns if a signal is pending, so the caller must check the return value"]
+ pub fn wait_interruptible_freezable<T: ?Sized, B: Backend>(
+ &self,
+ guard: &mut Guard<'_, T, B>,
+ ) -> bool {
+ self.wait_internal(
+ TASK_INTERRUPTIBLE | TASK_FREEZABLE,
+ guard,
+ MAX_SCHEDULE_TIMEOUT,
+ );
+ crate::current!().signal_pending()
+ }
+
/// Releases the lock and waits for a notification in interruptible mode.
///
/// Atomically releases the given lock (whose ownership is proven by the guard) and puts the
diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index eb80048e0110..e82fa5be289c 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -7,13 +7,11 @@
use super::LockClassKey;
use crate::{
- init::PinInit,
- pin_init,
str::CStr,
types::{NotThreadSafe, Opaque, ScopeGuard},
};
-use core::{cell::UnsafeCell, marker::PhantomPinned};
-use macros::pin_data;
+use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin};
+use pin_init::{pin_data, pin_init, PinInit};
pub mod mutex;
pub mod spinlock;
@@ -129,7 +127,7 @@ unsafe impl<T: ?Sized + Send, B: Backend> Sync for Lock<T, B> {}
impl<T, B: Backend> Lock<T, B> {
/// Constructs a new lock initialiser.
- pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
+ pub fn new(t: T, name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self> {
pin_init!(Self {
data: UnsafeCell::new(t),
_pin: PhantomPinned,
@@ -199,7 +197,37 @@ pub struct Guard<'a, T: ?Sized, B: Backend> {
// SAFETY: `Guard` is sync when the data protected by the lock is also sync.
unsafe impl<T: Sync + ?Sized, B: Backend> Sync for Guard<'_, T, B> {}
-impl<T: ?Sized, B: Backend> Guard<'_, T, B> {
+impl<'a, T: ?Sized, B: Backend> Guard<'a, T, B> {
+ /// Returns the lock that this guard originates from.
+ ///
+ /// # Examples
+ ///
+ /// The following example shows how to use [`Guard::lock_ref()`] to assert the corresponding
+ /// lock is held.
+ ///
+ /// ```
+ /// # use kernel::{new_spinlock, sync::lock::{Backend, Guard, Lock}};
+ /// # use pin_init::stack_pin_init;
+ ///
+ /// fn assert_held<T, B: Backend>(guard: &Guard<'_, T, B>, lock: &Lock<T, B>) {
+ /// // Address-equal means the same lock.
+ /// assert!(core::ptr::eq(guard.lock_ref(), lock));
+ /// }
+ ///
+ /// // Creates a new lock on the stack.
+ /// stack_pin_init!{
+ /// let l = new_spinlock!(42)
+ /// }
+ ///
+ /// let g = l.lock();
+ ///
+ /// // `g` originates from `l`.
+ /// assert_held(&g, &l);
+ /// ```
+ pub fn lock_ref(&self) -> &'a Lock<T, B> {
+ self.lock
+ }
+
pub(crate) fn do_unlocked<U>(&mut self, cb: impl FnOnce() -> U) -> U {
// SAFETY: The caller owns the lock, so it is safe to unlock it.
unsafe { B::unlock(self.lock.state.get(), &self.state) };
diff --git a/rust/kernel/sync/lock/global.rs b/rust/kernel/sync/lock/global.rs
index 480ee724e3cc..d65f94b5caf2 100644
--- a/rust/kernel/sync/lock/global.rs
+++ b/rust/kernel/sync/lock/global.rs
@@ -13,6 +13,7 @@ use crate::{
use core::{
cell::UnsafeCell,
marker::{PhantomData, PhantomPinned},
+ pin::Pin,
};
/// Trait implemented for marker types for global locks.
@@ -26,7 +27,7 @@ pub trait GlobalLockBackend {
/// The backend used for this global lock.
type Backend: Backend + 'static;
/// The class for this global lock.
- fn get_lock_class() -> &'static LockClassKey;
+ fn get_lock_class() -> Pin<&'static LockClassKey>;
}
/// Type used for global locks.
@@ -270,7 +271,7 @@ macro_rules! global_lock {
type Item = $valuety;
type Backend = $crate::global_lock_inner!(backend $kind);
- fn get_lock_class() -> &'static $crate::sync::LockClassKey {
+ fn get_lock_class() -> Pin<&'static $crate::sync::LockClassKey> {
$crate::static_lock_class!()
}
}
diff --git a/rust/kernel/sync/lock/mutex.rs b/rust/kernel/sync/lock/mutex.rs
index 70cadbc2e8e2..581cee7ab842 100644
--- a/rust/kernel/sync/lock/mutex.rs
+++ b/rust/kernel/sync/lock/mutex.rs
@@ -26,7 +26,7 @@ pub use new_mutex;
/// Since it may block, [`Mutex`] needs to be used with care in atomic contexts.
///
/// Instances of [`Mutex`] need a lock class and to be pinned. The recommended way to create such
-/// instances is with the [`pin_init`](crate::pin_init) and [`new_mutex`] macros.
+/// instances is with the [`pin_init`](pin_init::pin_init) and [`new_mutex`] macros.
///
/// # Examples
///
diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spinlock.rs
index ab2f8d075311..d7be38ccbdc7 100644
--- a/rust/kernel/sync/lock/spinlock.rs
+++ b/rust/kernel/sync/lock/spinlock.rs
@@ -24,7 +24,7 @@ pub use new_spinlock;
/// unlocked, at which point another CPU will be allowed to make progress.
///
/// Instances of [`SpinLock`] need a lock class and to be pinned. The recommended way to create such
-/// instances is with the [`pin_init`](crate::pin_init) and [`new_spinlock`] macros.
+/// instances is with the [`pin_init`](pin_init::pin_init) and [`new_spinlock`] macros.
///
/// # Examples
///
diff --git a/rust/kernel/sync/poll.rs b/rust/kernel/sync/poll.rs
index d5f17153b424..d7e6e59e124b 100644
--- a/rust/kernel/sync/poll.rs
+++ b/rust/kernel/sync/poll.rs
@@ -43,11 +43,11 @@ impl PollTable {
///
/// # Safety
///
- /// The caller must ensure that for the duration of 'a, the pointer will point at a valid poll
+ /// The caller must ensure that for the duration of `'a`, the pointer will point at a valid poll
/// table (as defined in the type invariants).
///
/// The caller must also ensure that the `poll_table` is only accessed via the returned
- /// reference for the duration of 'a.
+ /// reference for the duration of `'a`.
pub unsafe fn from_ptr<'a>(ptr: *mut bindings::poll_table) -> &'a mut PollTable {
// SAFETY: The safety requirements guarantee the validity of the dereference, while the
// `PollTable` type being transparent makes the cast ok.
@@ -89,7 +89,7 @@ pub struct PollCondVar {
impl PollCondVar {
/// Constructs a new condvar initialiser.
- pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
+ pub fn new(name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self> {
pin_init!(Self {
inner <- CondVar::new(name, key),
})
diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 38da555a2bdb..9e6f6854948d 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -23,6 +23,8 @@ pub const MAX_SCHEDULE_TIMEOUT: c_long = c_long::MAX;
pub const TASK_INTERRUPTIBLE: c_int = bindings::TASK_INTERRUPTIBLE as c_int;
/// Bitmask for tasks that are sleeping in an uninterruptible state.
pub const TASK_UNINTERRUPTIBLE: c_int = bindings::TASK_UNINTERRUPTIBLE as c_int;
+/// Bitmask for tasks that are sleeping in a freezable state.
+pub const TASK_FREEZABLE: c_int = bindings::TASK_FREEZABLE as c_int;
/// Convenience constant for waking up tasks regardless of whether they are in interruptible or
/// uninterruptible sleep.
pub const TASK_NORMAL: c_uint = bindings::TASK_NORMAL as c_uint;
@@ -106,7 +108,7 @@ unsafe impl Send for Task {}
unsafe impl Sync for Task {}
/// The type of process identifiers (PIDs).
-type Pid = bindings::pid_t;
+pub type Pid = bindings::pid_t;
/// The type of user identifiers (UIDs).
#[derive(Copy, Clone)]
diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index 379c0f5772e5..f509cb0eb71e 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -8,6 +8,8 @@
//! C header: [`include/linux/jiffies.h`](srctree/include/linux/jiffies.h).
//! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h).
+pub mod hrtimer;
+
/// The number of nanoseconds per millisecond.
pub const NSEC_PER_MSEC: i64 = bindings::NSEC_PER_MSEC as i64;
@@ -81,3 +83,69 @@ impl core::ops::Sub for Ktime {
}
}
}
+
+/// An identifier for a clock. Used when specifying clock sources.
+///
+///
+/// Selection of the clock depends on the use case. In some cases the usage of a
+/// particular clock is mandatory, e.g. in network protocols, filesystems.In other
+/// cases the user of the clock has to decide which clock is best suited for the
+/// purpose. In most scenarios clock [`ClockId::Monotonic`] is the best choice as it
+/// provides a accurate monotonic notion of time (leap second smearing ignored).
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[repr(u32)]
+pub enum ClockId {
+ /// A settable system-wide clock that measures real (i.e., wall-clock) time.
+ ///
+ /// Setting this clock requires appropriate privileges. This clock is
+ /// affected by discontinuous jumps in the system time (e.g., if the system
+ /// administrator manually changes the clock), and by frequency adjustments
+ /// performed by NTP and similar applications via adjtime(3), adjtimex(2),
+ /// clock_adjtime(2), and ntp_adjtime(3). This clock normally counts the
+ /// number of seconds since 1970-01-01 00:00:00 Coordinated Universal Time
+ /// (UTC) except that it ignores leap seconds; near a leap second it may be
+ /// adjusted by leap second smearing to stay roughly in sync with UTC. Leap
+ /// second smearing applies frequency adjustments to the clock to speed up
+ /// or slow down the clock to account for the leap second without
+ /// discontinuities in the clock. If leap second smearing is not applied,
+ /// the clock will experience discontinuity around leap second adjustment.
+ RealTime = bindings::CLOCK_REALTIME,
+ /// A monotonically increasing clock.
+ ///
+ /// A nonsettable system-wide clock that represents monotonic time since—as
+ /// described by POSIX—"some unspecified point in the past". On Linux, that
+ /// point corresponds to the number of seconds that the system has been
+ /// running since it was booted.
+ ///
+ /// The CLOCK_MONOTONIC clock is not affected by discontinuous jumps in the
+ /// CLOCK_REAL (e.g., if the system administrator manually changes the
+ /// clock), but is affected by frequency adjustments. This clock does not
+ /// count time that the system is suspended.
+ Monotonic = bindings::CLOCK_MONOTONIC,
+ /// A monotonic that ticks while system is suspended.
+ ///
+ /// A nonsettable system-wide clock that is identical to CLOCK_MONOTONIC,
+ /// except that it also includes any time that the system is suspended. This
+ /// allows applications to get a suspend-aware monotonic clock without
+ /// having to deal with the complications of CLOCK_REALTIME, which may have
+ /// discontinuities if the time is changed using settimeofday(2) or similar.
+ BootTime = bindings::CLOCK_BOOTTIME,
+ /// International Atomic Time.
+ ///
+ /// A system-wide clock derived from wall-clock time but counting leap seconds.
+ ///
+ /// This clock is coupled to CLOCK_REALTIME and will be set when CLOCK_REALTIME is
+ /// set, or when the offset to CLOCK_REALTIME is changed via adjtimex(2). This
+ /// usually happens during boot and **should** not happen during normal operations.
+ /// However, if NTP or another application adjusts CLOCK_REALTIME by leap second
+ /// smearing, this clock will not be precise during leap second smearing.
+ ///
+ /// The acronym TAI refers to International Atomic Time.
+ TAI = bindings::CLOCK_TAI,
+}
+
+impl ClockId {
+ fn into_c(self) -> bindings::clockid_t {
+ self as bindings::clockid_t
+ }
+}
diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
new file mode 100644
index 000000000000..ce53f8579d18
--- /dev/null
+++ b/rust/kernel/time/hrtimer.rs
@@ -0,0 +1,520 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Intrusive high resolution timers.
+//!
+//! Allows running timer callbacks without doing allocations at the time of
+//! starting the timer. For now, only one timer per type is allowed.
+//!
+//! # Vocabulary
+//!
+//! States:
+//!
+//! - Stopped: initialized but not started, or cancelled, or not restarted.
+//! - Started: initialized and started or restarted.
+//! - Running: executing the callback.
+//!
+//! Operations:
+//!
+//! * Start
+//! * Cancel
+//! * Restart
+//!
+//! Events:
+//!
+//! * Expire
+//!
+//! ## State Diagram
+//!
+//! ```text
+//! Return NoRestart
+//! +---------------------------------------------------------------------+
+//! | |
+//! | |
+//! | |
+//! | Return Restart |
+//! | +------------------------+ |
+//! | | | |
+//! | | | |
+//! v v | |
+//! +-----------------+ Start +------------------+ +--------+-----+--+
+//! | +---------------->| | | |
+//! Init | | | | Expire | |
+//! --------->| Stopped | | Started +---------->| Running |
+//! | | Cancel | | | |
+//! | |<----------------+ | | |
+//! +-----------------+ +---------------+--+ +-----------------+
+//! ^ |
+//! | |
+//! +---------+
+//! Restart
+//! ```
+//!
+//!
+//! A timer is initialized in the **stopped** state. A stopped timer can be
+//! **started** by the `start` operation, with an **expiry** time. After the
+//! `start` operation, the timer is in the **started** state. When the timer
+//! **expires**, the timer enters the **running** state and the handler is
+//! executed. After the handler has returned, the timer may enter the
+//! **started* or **stopped** state, depending on the return value of the
+//! handler. A timer in the **started** or **running** state may be **canceled**
+//! by the `cancel` operation. A timer that is cancelled enters the **stopped**
+//! state.
+//!
+//! A `cancel` or `restart` operation on a timer in the **running** state takes
+//! effect after the handler has returned and the timer has transitioned
+//! out of the **running** state.
+//!
+//! A `restart` operation on a timer in the **stopped** state is equivalent to a
+//! `start` operation.
+
+use super::ClockId;
+use crate::{prelude::*, time::Ktime, types::Opaque};
+use core::marker::PhantomData;
+use pin_init::PinInit;
+
+/// A timer backed by a C `struct hrtimer`.
+///
+/// # Invariants
+///
+/// * `self.timer` is initialized by `bindings::hrtimer_setup`.
+#[pin_data]
+#[repr(C)]
+pub struct HrTimer<T> {
+ #[pin]
+ timer: Opaque<bindings::hrtimer>,
+ mode: HrTimerMode,
+ _t: PhantomData<T>,
+}
+
+// SAFETY: Ownership of an `HrTimer` can be moved to other threads and
+// used/dropped from there.
+unsafe impl<T> Send for HrTimer<T> {}
+
+// SAFETY: Timer operations are locked on the C side, so it is safe to operate
+// on a timer from multiple threads.
+unsafe impl<T> Sync for HrTimer<T> {}
+
+impl<T> HrTimer<T> {
+ /// Return an initializer for a new timer instance.
+ pub fn new(mode: HrTimerMode, clock: ClockId) -> impl PinInit<Self>
+ where
+ T: HrTimerCallback,
+ {
+ pin_init!(Self {
+ // INVARIANT: We initialize `timer` with `hrtimer_setup` below.
+ timer <- Opaque::ffi_init(move |place: *mut bindings::hrtimer| {
+ // SAFETY: By design of `pin_init!`, `place` is a pointer to a
+ // live allocation. hrtimer_setup will initialize `place` and
+ // does not require `place` to be initialized prior to the call.
+ unsafe {
+ bindings::hrtimer_setup(
+ place,
+ Some(T::Pointer::run),
+ clock.into_c(),
+ mode.into_c(),
+ );
+ }
+ }),
+ mode: mode,
+ _t: PhantomData,
+ })
+ }
+
+ /// Get a pointer to the contained `bindings::hrtimer`.
+ ///
+ /// This function is useful to get access to the value without creating
+ /// intermediate references.
+ ///
+ /// # Safety
+ ///
+ /// `this` must point to a live allocation of at least the size of `Self`.
+ unsafe fn raw_get(this: *const Self) -> *mut bindings::hrtimer {
+ // SAFETY: The field projection to `timer` does not go out of bounds,
+ // because the caller of this function promises that `this` points to an
+ // allocation of at least the size of `Self`.
+ unsafe { Opaque::raw_get(core::ptr::addr_of!((*this).timer)) }
+ }
+
+ /// Cancel an initialized and potentially running timer.
+ ///
+ /// If the timer handler is running, this function will block until the
+ /// handler returns.
+ ///
+ /// Note that the timer might be started by a concurrent start operation. If
+ /// so, the timer might not be in the **stopped** state when this function
+ /// returns.
+ ///
+ /// Users of the `HrTimer` API would not usually call this method directly.
+ /// Instead they would use the safe [`HrTimerHandle::cancel`] on the handle
+ /// returned when the timer was started.
+ ///
+ /// This function is useful to get access to the value without creating
+ /// intermediate references.
+ ///
+ /// # Safety
+ ///
+ /// `this` must point to a valid `Self`.
+ pub(crate) unsafe fn raw_cancel(this: *const Self) -> bool {
+ // SAFETY: `this` points to an allocation of at least `HrTimer` size.
+ let c_timer_ptr = unsafe { HrTimer::raw_get(this) };
+
+ // If the handler is running, this will wait for the handler to return
+ // before returning.
+ // SAFETY: `c_timer_ptr` is initialized and valid. Synchronization is
+ // handled on the C side.
+ unsafe { bindings::hrtimer_cancel(c_timer_ptr) != 0 }
+ }
+}
+
+/// Implemented by pointer types that point to structs that contain a [`HrTimer`].
+///
+/// `Self` must be [`Sync`] because it is passed to timer callbacks in another
+/// thread of execution (hard or soft interrupt context).
+///
+/// Starting a timer returns a [`HrTimerHandle`] that can be used to manipulate
+/// the timer. Note that it is OK to call the start function repeatedly, and
+/// that more than one [`HrTimerHandle`] associated with a [`HrTimerPointer`] may
+/// exist. A timer can be manipulated through any of the handles, and a handle
+/// may represent a cancelled timer.
+pub trait HrTimerPointer: Sync + Sized {
+ /// A handle representing a started or restarted timer.
+ ///
+ /// If the timer is running or if the timer callback is executing when the
+ /// handle is dropped, the drop method of [`HrTimerHandle`] should not return
+ /// until the timer is stopped and the callback has completed.
+ ///
+ /// Note: When implementing this trait, consider that it is not unsafe to
+ /// leak the handle.
+ type TimerHandle: HrTimerHandle;
+
+ /// Start the timer with expiry after `expires` time units. If the timer was
+ /// already running, it is restarted with the new expiry time.
+ fn start(self, expires: Ktime) -> Self::TimerHandle;
+}
+
+/// Unsafe version of [`HrTimerPointer`] for situations where leaking the
+/// [`HrTimerHandle`] returned by `start` would be unsound. This is the case for
+/// stack allocated timers.
+///
+/// Typical implementers are pinned references such as [`Pin<&T>`].
+///
+/// # Safety
+///
+/// Implementers of this trait must ensure that instances of types implementing
+/// [`UnsafeHrTimerPointer`] outlives any associated [`HrTimerPointer::TimerHandle`]
+/// instances.
+pub unsafe trait UnsafeHrTimerPointer: Sync + Sized {
+ /// A handle representing a running timer.
+ ///
+ /// # Safety
+ ///
+ /// If the timer is running, or if the timer callback is executing when the
+ /// handle is dropped, the drop method of [`Self::TimerHandle`] must not return
+ /// until the timer is stopped and the callback has completed.
+ type TimerHandle: HrTimerHandle;
+
+ /// Start the timer after `expires` time units. If the timer was already
+ /// running, it is restarted at the new expiry time.
+ ///
+ /// # Safety
+ ///
+ /// Caller promises keep the timer structure alive until the timer is dead.
+ /// Caller can ensure this by not leaking the returned [`Self::TimerHandle`].
+ unsafe fn start(self, expires: Ktime) -> Self::TimerHandle;
+}
+
+/// A trait for stack allocated timers.
+///
+/// # Safety
+///
+/// Implementers must ensure that `start_scoped` does not return until the
+/// timer is dead and the timer handler is not running.
+pub unsafe trait ScopedHrTimerPointer {
+ /// Start the timer to run after `expires` time units and immediately
+ /// after call `f`. When `f` returns, the timer is cancelled.
+ fn start_scoped<T, F>(self, expires: Ktime, f: F) -> T
+ where
+ F: FnOnce() -> T;
+}
+
+// SAFETY: By the safety requirement of [`UnsafeHrTimerPointer`], dropping the
+// handle returned by [`UnsafeHrTimerPointer::start`] ensures that the timer is
+// killed.
+unsafe impl<T> ScopedHrTimerPointer for T
+where
+ T: UnsafeHrTimerPointer,
+{
+ fn start_scoped<U, F>(self, expires: Ktime, f: F) -> U
+ where
+ F: FnOnce() -> U,
+ {
+ // SAFETY: We drop the timer handle below before returning.
+ let handle = unsafe { UnsafeHrTimerPointer::start(self, expires) };
+ let t = f();
+ drop(handle);
+ t
+ }
+}
+
+/// Implemented by [`HrTimerPointer`] implementers to give the C timer callback a
+/// function to call.
+// This is split from `HrTimerPointer` to make it easier to specify trait bounds.
+pub trait RawHrTimerCallback {
+ /// Type of the parameter passed to [`HrTimerCallback::run`]. It may be
+ /// [`Self`], or a pointer type derived from [`Self`].
+ type CallbackTarget<'a>;
+
+ /// Callback to be called from C when timer fires.
+ ///
+ /// # Safety
+ ///
+ /// Only to be called by C code in the `hrtimer` subsystem. `this` must point
+ /// to the `bindings::hrtimer` structure that was used to start the timer.
+ unsafe extern "C" fn run(this: *mut bindings::hrtimer) -> bindings::hrtimer_restart;
+}
+
+/// Implemented by structs that can be the target of a timer callback.
+pub trait HrTimerCallback {
+ /// The type whose [`RawHrTimerCallback::run`] method will be invoked when
+ /// the timer expires.
+ type Pointer<'a>: RawHrTimerCallback;
+
+ /// Called by the timer logic when the timer fires.
+ fn run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart
+ where
+ Self: Sized;
+}
+
+/// A handle representing a potentially running timer.
+///
+/// More than one handle representing the same timer might exist.
+///
+/// # Safety
+///
+/// When dropped, the timer represented by this handle must be cancelled, if it
+/// is running. If the timer handler is running when the handle is dropped, the
+/// drop method must wait for the handler to return before returning.
+///
+/// Note: One way to satisfy the safety requirement is to call `Self::cancel` in
+/// the drop implementation for `Self.`
+pub unsafe trait HrTimerHandle {
+ /// Cancel the timer. If the timer is in the running state, block till the
+ /// handler has returned.
+ ///
+ /// Note that the timer might be started by a concurrent start operation. If
+ /// so, the timer might not be in the **stopped** state when this function
+ /// returns.
+ fn cancel(&mut self) -> bool;
+}
+
+/// Implemented by structs that contain timer nodes.
+///
+/// Clients of the timer API would usually safely implement this trait by using
+/// the [`crate::impl_has_hr_timer`] macro.
+///
+/// # Safety
+///
+/// Implementers of this trait must ensure that the implementer has a
+/// [`HrTimer`] field and that all trait methods are implemented according to
+/// their documentation. All the methods of this trait must operate on the same
+/// field.
+pub unsafe trait HasHrTimer<T> {
+ /// Return a pointer to the [`HrTimer`] within `Self`.
+ ///
+ /// This function is useful to get access to the value without creating
+ /// intermediate references.
+ ///
+ /// # Safety
+ ///
+ /// `this` must be a valid pointer.
+ unsafe fn raw_get_timer(this: *const Self) -> *const HrTimer<T>;
+
+ /// Return a pointer to the struct that is containing the [`HrTimer`] pointed
+ /// to by `ptr`.
+ ///
+ /// This function is useful to get access to the value without creating
+ /// intermediate references.
+ ///
+ /// # Safety
+ ///
+ /// `ptr` must point to a [`HrTimer<T>`] field in a struct of type `Self`.
+ unsafe fn timer_container_of(ptr: *mut HrTimer<T>) -> *mut Self
+ where
+ Self: Sized;
+
+ /// Get pointer to the contained `bindings::hrtimer` struct.
+ ///
+ /// This function is useful to get access to the value without creating
+ /// intermediate references.
+ ///
+ /// # Safety
+ ///
+ /// `this` must be a valid pointer.
+ unsafe fn c_timer_ptr(this: *const Self) -> *const bindings::hrtimer {
+ // SAFETY: `this` is a valid pointer to a `Self`.
+ let timer_ptr = unsafe { Self::raw_get_timer(this) };
+
+ // SAFETY: timer_ptr points to an allocation of at least `HrTimer` size.
+ unsafe { HrTimer::raw_get(timer_ptr) }
+ }
+
+ /// Start the timer contained in the `Self` pointed to by `self_ptr`. If
+ /// it is already running it is removed and inserted.
+ ///
+ /// # Safety
+ ///
+ /// - `this` must point to a valid `Self`.
+ /// - Caller must ensure that the pointee of `this` lives until the timer
+ /// fires or is canceled.
+ unsafe fn start(this: *const Self, expires: Ktime) {
+ // SAFETY: By function safety requirement, `this` is a valid `Self`.
+ unsafe {
+ bindings::hrtimer_start_range_ns(
+ Self::c_timer_ptr(this).cast_mut(),
+ expires.to_ns(),
+ 0,
+ (*Self::raw_get_timer(this)).mode.into_c(),
+ );
+ }
+ }
+}
+
+/// Restart policy for timers.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[repr(u32)]
+pub enum HrTimerRestart {
+ /// Timer should not be restarted.
+ #[allow(clippy::unnecessary_cast)]
+ NoRestart = bindings::hrtimer_restart_HRTIMER_NORESTART as u32,
+ /// Timer should be restarted.
+ #[allow(clippy::unnecessary_cast)]
+ Restart = bindings::hrtimer_restart_HRTIMER_RESTART as u32,
+}
+
+impl HrTimerRestart {
+ fn into_c(self) -> bindings::hrtimer_restart {
+ self as bindings::hrtimer_restart
+ }
+}
+
+/// Operational mode of [`HrTimer`].
+// NOTE: Some of these have the same encoding on the C side, so we keep
+// `repr(Rust)` and convert elsewhere.
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum HrTimerMode {
+ /// Timer expires at the given expiration time.
+ Absolute,
+ /// Timer expires after the given expiration time interpreted as a duration from now.
+ Relative,
+ /// Timer does not move between CPU cores.
+ Pinned,
+ /// Timer handler is executed in soft irq context.
+ Soft,
+ /// Timer handler is executed in hard irq context.
+ Hard,
+ /// Timer expires at the given expiration time.
+ /// Timer does not move between CPU cores.
+ AbsolutePinned,
+ /// Timer expires after the given expiration time interpreted as a duration from now.
+ /// Timer does not move between CPU cores.
+ RelativePinned,
+ /// Timer expires at the given expiration time.
+ /// Timer handler is executed in soft irq context.
+ AbsoluteSoft,
+ /// Timer expires after the given expiration time interpreted as a duration from now.
+ /// Timer handler is executed in soft irq context.
+ RelativeSoft,
+ /// Timer expires at the given expiration time.
+ /// Timer does not move between CPU cores.
+ /// Timer handler is executed in soft irq context.
+ AbsolutePinnedSoft,
+ /// Timer expires after the given expiration time interpreted as a duration from now.
+ /// Timer does not move between CPU cores.
+ /// Timer handler is executed in soft irq context.
+ RelativePinnedSoft,
+ /// Timer expires at the given expiration time.
+ /// Timer handler is executed in hard irq context.
+ AbsoluteHard,
+ /// Timer expires after the given expiration time interpreted as a duration from now.
+ /// Timer handler is executed in hard irq context.
+ RelativeHard,
+ /// Timer expires at the given expiration time.
+ /// Timer does not move between CPU cores.
+ /// Timer handler is executed in hard irq context.
+ AbsolutePinnedHard,
+ /// Timer expires after the given expiration time interpreted as a duration from now.
+ /// Timer does not move between CPU cores.
+ /// Timer handler is executed in hard irq context.
+ RelativePinnedHard,
+}
+
+impl HrTimerMode {
+ fn into_c(self) -> bindings::hrtimer_mode {
+ use bindings::*;
+ match self {
+ HrTimerMode::Absolute => hrtimer_mode_HRTIMER_MODE_ABS,
+ HrTimerMode::Relative => hrtimer_mode_HRTIMER_MODE_REL,
+ HrTimerMode::Pinned => hrtimer_mode_HRTIMER_MODE_PINNED,
+ HrTimerMode::Soft => hrtimer_mode_HRTIMER_MODE_SOFT,
+ HrTimerMode::Hard => hrtimer_mode_HRTIMER_MODE_HARD,
+ HrTimerMode::AbsolutePinned => hrtimer_mode_HRTIMER_MODE_ABS_PINNED,
+ HrTimerMode::RelativePinned => hrtimer_mode_HRTIMER_MODE_REL_PINNED,
+ HrTimerMode::AbsoluteSoft => hrtimer_mode_HRTIMER_MODE_ABS_SOFT,
+ HrTimerMode::RelativeSoft => hrtimer_mode_HRTIMER_MODE_REL_SOFT,
+ HrTimerMode::AbsolutePinnedSoft => hrtimer_mode_HRTIMER_MODE_ABS_PINNED_SOFT,
+ HrTimerMode::RelativePinnedSoft => hrtimer_mode_HRTIMER_MODE_REL_PINNED_SOFT,
+ HrTimerMode::AbsoluteHard => hrtimer_mode_HRTIMER_MODE_ABS_HARD,
+ HrTimerMode::RelativeHard => hrtimer_mode_HRTIMER_MODE_REL_HARD,
+ HrTimerMode::AbsolutePinnedHard => hrtimer_mode_HRTIMER_MODE_ABS_PINNED_HARD,
+ HrTimerMode::RelativePinnedHard => hrtimer_mode_HRTIMER_MODE_REL_PINNED_HARD,
+ }
+ }
+}
+
+/// Use to implement the [`HasHrTimer<T>`] trait.
+///
+/// See [`module`] documentation for an example.
+///
+/// [`module`]: crate::time::hrtimer
+#[macro_export]
+macro_rules! impl_has_hr_timer {
+ (
+ impl$({$($generics:tt)*})?
+ HasHrTimer<$timer_type:ty>
+ for $self:ty
+ { self.$field:ident }
+ $($rest:tt)*
+ ) => {
+ // SAFETY: This implementation of `raw_get_timer` only compiles if the
+ // field has the right type.
+ unsafe impl$(<$($generics)*>)? $crate::time::hrtimer::HasHrTimer<$timer_type> for $self {
+
+ #[inline]
+ unsafe fn raw_get_timer(
+ this: *const Self,
+ ) -> *const $crate::time::hrtimer::HrTimer<$timer_type> {
+ // SAFETY: The caller promises that the pointer is not dangling.
+ unsafe { ::core::ptr::addr_of!((*this).$field) }
+ }
+
+ #[inline]
+ unsafe fn timer_container_of(
+ ptr: *mut $crate::time::hrtimer::HrTimer<$timer_type>,
+ ) -> *mut Self {
+ // SAFETY: As per the safety requirement of this function, `ptr`
+ // is pointing inside a `$timer_type`.
+ unsafe { ::kernel::container_of!(ptr, $timer_type, $field).cast_mut() }
+ }
+ }
+ }
+}
+
+mod arc;
+pub use arc::ArcHrTimerHandle;
+mod pin;
+pub use pin::PinHrTimerHandle;
+mod pin_mut;
+pub use pin_mut::PinMutHrTimerHandle;
+// `box` is a reserved keyword, so prefix with `t` for timer
+mod tbox;
+pub use tbox::BoxHrTimerHandle;
diff --git a/rust/kernel/time/hrtimer/arc.rs b/rust/kernel/time/hrtimer/arc.rs
new file mode 100644
index 000000000000..4a984d85b4a1
--- /dev/null
+++ b/rust/kernel/time/hrtimer/arc.rs
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use super::HasHrTimer;
+use super::HrTimer;
+use super::HrTimerCallback;
+use super::HrTimerHandle;
+use super::HrTimerPointer;
+use super::RawHrTimerCallback;
+use crate::sync::Arc;
+use crate::sync::ArcBorrow;
+use crate::time::Ktime;
+
+/// A handle for an `Arc<HasHrTimer<T>>` returned by a call to
+/// [`HrTimerPointer::start`].
+pub struct ArcHrTimerHandle<T>
+where
+ T: HasHrTimer<T>,
+{
+ pub(crate) inner: Arc<T>,
+}
+
+// SAFETY: We implement drop below, and we cancel the timer in the drop
+// implementation.
+unsafe impl<T> HrTimerHandle for ArcHrTimerHandle<T>
+where
+ T: HasHrTimer<T>,
+{
+ fn cancel(&mut self) -> bool {
+ let self_ptr = Arc::as_ptr(&self.inner);
+
+ // SAFETY: As we obtained `self_ptr` from a valid reference above, it
+ // must point to a valid `T`.
+ let timer_ptr = unsafe { <T as HasHrTimer<T>>::raw_get_timer(self_ptr) };
+
+ // SAFETY: As `timer_ptr` points into `T` and `T` is valid, `timer_ptr`
+ // must point to a valid `HrTimer` instance.
+ unsafe { HrTimer::<T>::raw_cancel(timer_ptr) }
+ }
+}
+
+impl<T> Drop for ArcHrTimerHandle<T>
+where
+ T: HasHrTimer<T>,
+{
+ fn drop(&mut self) {
+ self.cancel();
+ }
+}
+
+impl<T> HrTimerPointer for Arc<T>
+where
+ T: 'static,
+ T: Send + Sync,
+ T: HasHrTimer<T>,
+ T: for<'a> HrTimerCallback<Pointer<'a> = Self>,
+{
+ type TimerHandle = ArcHrTimerHandle<T>;
+
+ fn start(self, expires: Ktime) -> ArcHrTimerHandle<T> {
+ // SAFETY:
+ // - We keep `self` alive by wrapping it in a handle below.
+ // - Since we generate the pointer passed to `start` from a valid
+ // reference, it is a valid pointer.
+ unsafe { T::start(Arc::as_ptr(&self), expires) };
+ ArcHrTimerHandle { inner: self }
+ }
+}
+
+impl<T> RawHrTimerCallback for Arc<T>
+where
+ T: 'static,
+ T: HasHrTimer<T>,
+ T: for<'a> HrTimerCallback<Pointer<'a> = Self>,
+{
+ type CallbackTarget<'a> = ArcBorrow<'a, T>;
+
+ unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart {
+ // `HrTimer` is `repr(C)`
+ let timer_ptr = ptr.cast::<super::HrTimer<T>>();
+
+ // SAFETY: By C API contract `ptr` is the pointer we passed when
+ // queuing the timer, so it is a `HrTimer<T>` embedded in a `T`.
+ let data_ptr = unsafe { T::timer_container_of(timer_ptr) };
+
+ // SAFETY:
+ // - `data_ptr` is derived form the pointer to the `T` that was used to
+ // queue the timer.
+ // - As per the safety requirements of the trait `HrTimerHandle`, the
+ // `ArcHrTimerHandle` associated with this timer is guaranteed to
+ // be alive until this method returns. That handle borrows the `T`
+ // behind `data_ptr` thus guaranteeing the validity of
+ // the `ArcBorrow` created below.
+ // - We own one refcount in the `ArcTimerHandle` associated with this
+ // timer, so it is not possible to get a `UniqueArc` to this
+ // allocation from other `Arc` clones.
+ let receiver = unsafe { ArcBorrow::from_raw(data_ptr) };
+
+ T::run(receiver).into_c()
+ }
+}
diff --git a/rust/kernel/time/hrtimer/pin.rs b/rust/kernel/time/hrtimer/pin.rs
new file mode 100644
index 000000000000..f760db265c7b
--- /dev/null
+++ b/rust/kernel/time/hrtimer/pin.rs
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use super::HasHrTimer;
+use super::HrTimer;
+use super::HrTimerCallback;
+use super::HrTimerHandle;
+use super::RawHrTimerCallback;
+use super::UnsafeHrTimerPointer;
+use crate::time::Ktime;
+use core::pin::Pin;
+
+/// A handle for a `Pin<&HasHrTimer>`. When the handle exists, the timer might be
+/// running.
+pub struct PinHrTimerHandle<'a, T>
+where
+ T: HasHrTimer<T>,
+{
+ pub(crate) inner: Pin<&'a T>,
+}
+
+// SAFETY: We cancel the timer when the handle is dropped. The implementation of
+// the `cancel` method will block if the timer handler is running.
+unsafe impl<'a, T> HrTimerHandle for PinHrTimerHandle<'a, T>
+where
+ T: HasHrTimer<T>,
+{
+ fn cancel(&mut self) -> bool {
+ let self_ptr: *const T = self.inner.get_ref();
+
+ // SAFETY: As we got `self_ptr` from a reference above, it must point to
+ // a valid `T`.
+ let timer_ptr = unsafe { <T as HasHrTimer<T>>::raw_get_timer(self_ptr) };
+
+ // SAFETY: As `timer_ptr` is derived from a reference, it must point to
+ // a valid and initialized `HrTimer`.
+ unsafe { HrTimer::<T>::raw_cancel(timer_ptr) }
+ }
+}
+
+impl<'a, T> Drop for PinHrTimerHandle<'a, T>
+where
+ T: HasHrTimer<T>,
+{
+ fn drop(&mut self) {
+ self.cancel();
+ }
+}
+
+// SAFETY: We capture the lifetime of `Self` when we create a `PinHrTimerHandle`,
+// so `Self` will outlive the handle.
+unsafe impl<'a, T> UnsafeHrTimerPointer for Pin<&'a T>
+where
+ T: Send + Sync,
+ T: HasHrTimer<T>,
+ T: HrTimerCallback<Pointer<'a> = Self>,
+{
+ type TimerHandle = PinHrTimerHandle<'a, T>;
+
+ unsafe fn start(self, expires: Ktime) -> Self::TimerHandle {
+ // Cast to pointer
+ let self_ptr: *const T = self.get_ref();
+
+ // SAFETY:
+ // - As we derive `self_ptr` from a reference above, it must point to a
+ // valid `T`.
+ // - We keep `self` alive by wrapping it in a handle below.
+ unsafe { T::start(self_ptr, expires) };
+
+ PinHrTimerHandle { inner: self }
+ }
+}
+
+impl<'a, T> RawHrTimerCallback for Pin<&'a T>
+where
+ T: HasHrTimer<T>,
+ T: HrTimerCallback<Pointer<'a> = Self>,
+{
+ type CallbackTarget<'b> = Self;
+
+ unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart {
+ // `HrTimer` is `repr(C)`
+ let timer_ptr = ptr as *mut HrTimer<T>;
+
+ // SAFETY: By the safety requirement of this function, `timer_ptr`
+ // points to a `HrTimer<T>` contained in an `T`.
+ let receiver_ptr = unsafe { T::timer_container_of(timer_ptr) };
+
+ // SAFETY:
+ // - By the safety requirement of this function, `timer_ptr`
+ // points to a `HrTimer<T>` contained in an `T`.
+ // - As per the safety requirements of the trait `HrTimerHandle`, the
+ // `PinHrTimerHandle` associated with this timer is guaranteed to
+ // be alive until this method returns. That handle borrows the `T`
+ // behind `receiver_ptr`, thus guaranteeing the validity of
+ // the reference created below.
+ let receiver_ref = unsafe { &*receiver_ptr };
+
+ // SAFETY: `receiver_ref` only exists as pinned, so it is safe to pin it
+ // here.
+ let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) };
+
+ T::run(receiver_pin).into_c()
+ }
+}
diff --git a/rust/kernel/time/hrtimer/pin_mut.rs b/rust/kernel/time/hrtimer/pin_mut.rs
new file mode 100644
index 000000000000..90c0351d62e4
--- /dev/null
+++ b/rust/kernel/time/hrtimer/pin_mut.rs
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use super::{
+ HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, RawHrTimerCallback, UnsafeHrTimerPointer,
+};
+use crate::time::Ktime;
+use core::{marker::PhantomData, pin::Pin, ptr::NonNull};
+
+/// A handle for a `Pin<&mut HasHrTimer>`. When the handle exists, the timer might
+/// be running.
+pub struct PinMutHrTimerHandle<'a, T>
+where
+ T: HasHrTimer<T>,
+{
+ pub(crate) inner: NonNull<T>,
+ _p: PhantomData<&'a mut T>,
+}
+
+// SAFETY: We cancel the timer when the handle is dropped. The implementation of
+// the `cancel` method will block if the timer handler is running.
+unsafe impl<'a, T> HrTimerHandle for PinMutHrTimerHandle<'a, T>
+where
+ T: HasHrTimer<T>,
+{
+ fn cancel(&mut self) -> bool {
+ let self_ptr = self.inner.as_ptr();
+
+ // SAFETY: As we got `self_ptr` from a reference above, it must point to
+ // a valid `T`.
+ let timer_ptr = unsafe { <T as HasHrTimer<T>>::raw_get_timer(self_ptr) };
+
+ // SAFETY: As `timer_ptr` is derived from a reference, it must point to
+ // a valid and initialized `HrTimer`.
+ unsafe { HrTimer::<T>::raw_cancel(timer_ptr) }
+ }
+}
+
+impl<'a, T> Drop for PinMutHrTimerHandle<'a, T>
+where
+ T: HasHrTimer<T>,
+{
+ fn drop(&mut self) {
+ self.cancel();
+ }
+}
+
+// SAFETY: We capture the lifetime of `Self` when we create a
+// `PinMutHrTimerHandle`, so `Self` will outlive the handle.
+unsafe impl<'a, T> UnsafeHrTimerPointer for Pin<&'a mut T>
+where
+ T: Send + Sync,
+ T: HasHrTimer<T>,
+ T: HrTimerCallback<Pointer<'a> = Self>,
+{
+ type TimerHandle = PinMutHrTimerHandle<'a, T>;
+
+ unsafe fn start(mut self, expires: Ktime) -> Self::TimerHandle {
+ // SAFETY:
+ // - We promise not to move out of `self`. We only pass `self`
+ // back to the caller as a `Pin<&mut self>`.
+ // - The return value of `get_unchecked_mut` is guaranteed not to be null.
+ let self_ptr = unsafe { NonNull::new_unchecked(self.as_mut().get_unchecked_mut()) };
+
+ // SAFETY:
+ // - As we derive `self_ptr` from a reference above, it must point to a
+ // valid `T`.
+ // - We keep `self` alive by wrapping it in a handle below.
+ unsafe { T::start(self_ptr.as_ptr(), expires) };
+
+ PinMutHrTimerHandle {
+ inner: self_ptr,
+ _p: PhantomData,
+ }
+ }
+}
+
+impl<'a, T> RawHrTimerCallback for Pin<&'a mut T>
+where
+ T: HasHrTimer<T>,
+ T: HrTimerCallback<Pointer<'a> = Self>,
+{
+ type CallbackTarget<'b> = Self;
+
+ unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart {
+ // `HrTimer` is `repr(C)`
+ let timer_ptr = ptr as *mut HrTimer<T>;
+
+ // SAFETY: By the safety requirement of this function, `timer_ptr`
+ // points to a `HrTimer<T>` contained in an `T`.
+ let receiver_ptr = unsafe { T::timer_container_of(timer_ptr) };
+
+ // SAFETY:
+ // - By the safety requirement of this function, `timer_ptr`
+ // points to a `HrTimer<T>` contained in an `T`.
+ // - As per the safety requirements of the trait `HrTimerHandle`, the
+ // `PinMutHrTimerHandle` associated with this timer is guaranteed to
+ // be alive until this method returns. That handle borrows the `T`
+ // behind `receiver_ptr` mutably thus guaranteeing the validity of
+ // the reference created below.
+ let receiver_ref = unsafe { &mut *receiver_ptr };
+
+ // SAFETY: `receiver_ref` only exists as pinned, so it is safe to pin it
+ // here.
+ let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) };
+
+ T::run(receiver_pin).into_c()
+ }
+}
diff --git a/rust/kernel/time/hrtimer/tbox.rs b/rust/kernel/time/hrtimer/tbox.rs
new file mode 100644
index 000000000000..2071cae07234
--- /dev/null
+++ b/rust/kernel/time/hrtimer/tbox.rs
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use super::HasHrTimer;
+use super::HrTimer;
+use super::HrTimerCallback;
+use super::HrTimerHandle;
+use super::HrTimerPointer;
+use super::RawHrTimerCallback;
+use crate::prelude::*;
+use crate::time::Ktime;
+use core::ptr::NonNull;
+
+/// A handle for a [`Box<HasHrTimer<T>>`] returned by a call to
+/// [`HrTimerPointer::start`].
+///
+/// # Invariants
+///
+/// - `self.inner` comes from a `Box::into_raw` call.
+pub struct BoxHrTimerHandle<T, A>
+where
+ T: HasHrTimer<T>,
+ A: crate::alloc::Allocator,
+{
+ pub(crate) inner: NonNull<T>,
+ _p: core::marker::PhantomData<A>,
+}
+
+// SAFETY: We implement drop below, and we cancel the timer in the drop
+// implementation.
+unsafe impl<T, A> HrTimerHandle for BoxHrTimerHandle<T, A>
+where
+ T: HasHrTimer<T>,
+ A: crate::alloc::Allocator,
+{
+ fn cancel(&mut self) -> bool {
+ // SAFETY: As we obtained `self.inner` from a valid reference when we
+ // created `self`, it must point to a valid `T`.
+ let timer_ptr = unsafe { <T as HasHrTimer<T>>::raw_get_timer(self.inner.as_ptr()) };
+
+ // SAFETY: As `timer_ptr` points into `T` and `T` is valid, `timer_ptr`
+ // must point to a valid `HrTimer` instance.
+ unsafe { HrTimer::<T>::raw_cancel(timer_ptr) }
+ }
+}
+
+impl<T, A> Drop for BoxHrTimerHandle<T, A>
+where
+ T: HasHrTimer<T>,
+ A: crate::alloc::Allocator,
+{
+ fn drop(&mut self) {
+ self.cancel();
+ // SAFETY: By type invariant, `self.inner` came from a `Box::into_raw`
+ // call.
+ drop(unsafe { Box::<T, A>::from_raw(self.inner.as_ptr()) })
+ }
+}
+
+impl<T, A> HrTimerPointer for Pin<Box<T, A>>
+where
+ T: 'static,
+ T: Send + Sync,
+ T: HasHrTimer<T>,
+ T: for<'a> HrTimerCallback<Pointer<'a> = Pin<Box<T, A>>>,
+ A: crate::alloc::Allocator,
+{
+ type TimerHandle = BoxHrTimerHandle<T, A>;
+
+ fn start(self, expires: Ktime) -> Self::TimerHandle {
+ // SAFETY:
+ // - We will not move out of this box during timer callback (we pass an
+ // immutable reference to the callback).
+ // - `Box::into_raw` is guaranteed to return a valid pointer.
+ let inner =
+ unsafe { NonNull::new_unchecked(Box::into_raw(Pin::into_inner_unchecked(self))) };
+
+ // SAFETY:
+ // - We keep `self` alive by wrapping it in a handle below.
+ // - Since we generate the pointer passed to `start` from a valid
+ // reference, it is a valid pointer.
+ unsafe { T::start(inner.as_ptr(), expires) };
+
+ // INVARIANT: `inner` came from `Box::into_raw` above.
+ BoxHrTimerHandle {
+ inner,
+ _p: core::marker::PhantomData,
+ }
+ }
+}
+
+impl<T, A> RawHrTimerCallback for Pin<Box<T, A>>
+where
+ T: 'static,
+ T: HasHrTimer<T>,
+ T: for<'a> HrTimerCallback<Pointer<'a> = Pin<Box<T, A>>>,
+ A: crate::alloc::Allocator,
+{
+ type CallbackTarget<'a> = Pin<&'a mut T>;
+
+ unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart {
+ // `HrTimer` is `repr(C)`
+ let timer_ptr = ptr.cast::<super::HrTimer<T>>();
+
+ // SAFETY: By C API contract `ptr` is the pointer we passed when
+ // queuing the timer, so it is a `HrTimer<T>` embedded in a `T`.
+ let data_ptr = unsafe { T::timer_container_of(timer_ptr) };
+
+ // SAFETY:
+ // - As per the safety requirements of the trait `HrTimerHandle`, the
+ // `BoxHrTimerHandle` associated with this timer is guaranteed to
+ // be alive until this method returns. That handle owns the `T`
+ // behind `data_ptr` thus guaranteeing the validity of
+ // the reference created below.
+ // - As `data_ptr` comes from a `Pin<Box<T>>`, only pinned references to
+ // `data_ptr` exist.
+ let data_mut_ref = unsafe { Pin::new_unchecked(&mut *data_ptr) };
+
+ T::run(data_mut_ref).into_c()
+ }
+}
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index 2bbaab83b9d6..9d0471afc964 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -2,7 +2,6 @@
//! Kernel types.
-use crate::init::{self, PinInit};
use core::{
cell::UnsafeCell,
marker::{PhantomData, PhantomPinned},
@@ -10,6 +9,7 @@ use core::{
ops::{Deref, DerefMut},
ptr::NonNull,
};
+use pin_init::{PinInit, Zeroable};
/// Used to transfer ownership to and from foreign (non-Rust) languages.
///
@@ -77,7 +77,7 @@ pub trait ForeignOwnable: Sized {
///
/// The provided pointer must have been returned by a previous call to [`into_foreign`], and if
/// the pointer is ever passed to [`from_foreign`], then that call must happen after the end of
- /// the lifetime 'a.
+ /// the lifetime `'a`.
///
/// [`into_foreign`]: Self::into_foreign
/// [`from_foreign`]: Self::from_foreign
@@ -100,9 +100,9 @@ pub trait ForeignOwnable: Sized {
///
/// The provided pointer must have been returned by a previous call to [`into_foreign`], and if
/// the pointer is ever passed to [`from_foreign`], then that call must happen after the end of
- /// the lifetime 'a.
+ /// the lifetime `'a`.
///
- /// The lifetime 'a must not overlap with the lifetime of any other call to [`borrow`] or
+ /// The lifetime `'a` must not overlap with the lifetime of any other call to [`borrow`] or
/// `borrow_mut` on the same object.
///
/// [`into_foreign`]: Self::into_foreign
@@ -251,7 +251,7 @@ impl<T, F: FnOnce(T)> Drop for ScopeGuard<T, F> {
/// Stores an opaque value.
///
-/// `Opaque<T>` is meant to be used with FFI objects that are never interpreted by Rust code.
+/// [`Opaque<T>`] is meant to be used with FFI objects that are never interpreted by Rust code.
///
/// It is used to wrap structs from the C side, like for example `Opaque<bindings::mutex>`.
/// It gets rid of all the usual assumptions that Rust has for a value:
@@ -266,7 +266,7 @@ impl<T, F: FnOnce(T)> Drop for ScopeGuard<T, F> {
/// This has to be used for all values that the C side has access to, because it can't be ensured
/// that the C side is adhering to the usual constraints that Rust needs.
///
-/// Using `Opaque<T>` allows to continue to use references on the Rust side even for values shared
+/// Using [`Opaque<T>`] allows to continue to use references on the Rust side even for values shared
/// with C.
///
/// # Examples
@@ -309,6 +309,9 @@ pub struct Opaque<T> {
_pin: PhantomPinned,
}
+// SAFETY: `Opaque<T>` allows the inner value to be any bit pattern, including all zeros.
+unsafe impl<T> Zeroable for Opaque<T> {}
+
impl<T> Opaque<T> {
/// Creates a new opaque value.
pub const fn new(value: T) -> Self {
@@ -333,7 +336,7 @@ impl<T> Opaque<T> {
// - `ptr` is a valid pointer to uninitialized memory,
// - `slot` is not accessed on error; the call is infallible,
// - `slot` is pinned in memory.
- let _ = unsafe { init::PinInit::<T>::__pinned_init(slot, ptr) };
+ let _ = unsafe { PinInit::<T>::__pinned_init(slot, ptr) };
})
}
@@ -349,7 +352,7 @@ impl<T> Opaque<T> {
// SAFETY: We contain a `MaybeUninit`, so it is OK for the `init_func` to not fully
// initialize the `T`.
unsafe {
- init::pin_init_from_closure::<_, ::core::convert::Infallible>(move |slot| {
+ pin_init::pin_init_from_closure::<_, ::core::convert::Infallible>(move |slot| {
init_func(Self::raw_get(slot));
Ok(())
})
@@ -369,7 +372,9 @@ impl<T> Opaque<T> {
) -> impl PinInit<Self, E> {
// SAFETY: We contain a `MaybeUninit`, so it is OK for the `init_func` to not fully
// initialize the `T`.
- unsafe { init::pin_init_from_closure::<_, E>(move |slot| init_func(Self::raw_get(slot))) }
+ unsafe {
+ pin_init::pin_init_from_closure::<_, E>(move |slot| init_func(Self::raw_get(slot)))
+ }
}
/// Returns a raw pointer to the opaque data.
diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs
index 719b0a48ff55..80a9782b1c6e 100644
--- a/rust/kernel/uaccess.rs
+++ b/rust/kernel/uaccess.rs
@@ -285,8 +285,7 @@ impl UserSliceReader {
let len = self.length;
buf.reserve(len, flags)?;
- // The call to `try_reserve` was successful, so the spare capacity is at least `len` bytes
- // long.
+ // The call to `reserve` was successful, so the spare capacity is at least `len` bytes long.
self.read_raw(&mut buf.spare_capacity_mut()[..len])?;
// SAFETY: Since the call to `read_raw` was successful, so the next `len` bytes of the
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index b7be224cdf4b..f98bd02b838f 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -369,7 +369,7 @@ unsafe impl<T: ?Sized, const ID: u64> Sync for Work<T, ID> {}
impl<T: ?Sized, const ID: u64> Work<T, ID> {
/// Creates a new instance of [`Work`].
#[inline]
- pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self>
+ pub fn new(name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self>
where
T: WorkItem<ID>,
{
@@ -703,3 +703,21 @@ pub fn system_freezable_power_efficient() -> &'static Queue {
// SAFETY: `system_freezable_power_efficient_wq` is a C global, always available.
unsafe { Queue::from_raw(bindings::system_freezable_power_efficient_wq) }
}
+
+/// Returns the system bottom halves work queue (`system_bh_wq`).
+///
+/// It is similar to the one returned by [`system`] but for work items which
+/// need to run from a softirq context.
+pub fn system_bh() -> &'static Queue {
+ // SAFETY: `system_bh_wq` is a C global, always available.
+ unsafe { Queue::from_raw(bindings::system_bh_wq) }
+}
+
+/// Returns the system bottom halves high-priority work queue (`system_bh_highpri_wq`).
+///
+/// It is similar to the one returned by [`system_bh`] but for work items which
+/// require higher scheduling priority.
+pub fn system_bh_highpri() -> &'static Queue {
+ // SAFETY: `system_bh_highpri_wq` is a C global, always available.
+ unsafe { Queue::from_raw(bindings::system_bh_highpri_wq) }
+}