diff options
author | 2023-06-26 09:35:50 -0700 | |
---|---|---|
committer | 2023-06-26 09:35:50 -0700 | |
commit | a1257b5e3b7f8a21faf462d0118067fe31e71ffb (patch) | |
tree | 75a05d9bc748ec2cd6552337800bc102949e9304 /rust/kernel | |
parent | Merge tag 's390-6.4-4' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux (diff) | |
parent | rust: error: `impl Debug` for `Error` with `errname()` integration (diff) | |
download | wireguard-linux-a1257b5e3b7f8a21faf462d0118067fe31e71ffb.tar.xz wireguard-linux-a1257b5e3b7f8a21faf462d0118067fe31e71ffb.zip |
Merge tag 'rust-6.5' of https://github.com/Rust-for-Linux/linux
Pull rust updates from Miguel Ojeda:
"A fairly small one in terms of feature additions. Most of the changes
in terms of lines come from the upgrade to the new version of the
toolchain (which in turn is big due to the vendored 'alloc' crate).
Upgrade to Rust 1.68.2:
- This is the first such upgrade, and we will try to update it often
from now on, in order to remain close to the latest release, until
a minimum version (which is "in the future") can be established.
The upgrade brings the stabilization of 4 features we used (and 2
more that we used in our old 'rust' branch).
Commit 3ed03f4da06e ("rust: upgrade to Rust 1.68.2") contains the
details and rationale.
pin-init API:
- Several internal improvements and fixes to the pin-init API, e.g.
allowing to use 'Self' in a struct definition with '#[pin_data]'.
'error' module:
- New 'name()' method for the 'Error' type (with 'errname()'
integration), used to implement the 'Debug' trait for 'Error'.
- Add error codes from 'include/linux/errno.h' to the list of Rust
'Error' constants.
- Allow specifying error type on the 'Result' type (with the default
still being our usual 'Error' type).
'str' module:
- 'TryFrom' implementation for 'CStr', and new 'to_cstring()' method
based on it.
'sync' module:
- Implement 'AsRef' trait for 'Arc', allowing to use 'Arc' in code
that is generic over smart pointer types.
- Add 'ptr_eq' method to 'Arc' for easier, less error prone
comparison between two 'Arc' pointers.
- Reword the 'Send' safety comment for 'Arc', and avoid referencing
it from the 'Sync' one.
'task' module:
- Implement 'Send' marker for 'Task'.
'types' module:
- Implement 'Send' and 'Sync' markers for 'ARef<T>' when 'T' is
'AlwaysRefCounted', 'Send' and 'Sync'.
Other changes:
- Documentation improvements and '.gitattributes' change to start
using the Rust diff driver"
* tag 'rust-6.5' of https://github.com/Rust-for-Linux/linux:
rust: error: `impl Debug` for `Error` with `errname()` integration
rust: task: add `Send` marker to `Task`
rust: specify when `ARef` is thread safe
rust: sync: reword the `Arc` safety comment for `Sync`
rust: sync: reword the `Arc` safety comment for `Send`
rust: sync: implement `AsRef<T>` for `Arc<T>`
rust: sync: add `Arc::ptr_eq`
rust: error: add missing error codes
rust: str: add conversion from `CStr` to `CString`
rust: error: allow specifying error type on `Result`
rust: init: update macro expansion example in docs
rust: macros: replace Self with the concrete type in #[pin_data]
rust: macros: refactor generics parsing of `#[pin_data]` into its own function
rust: macros: fix usage of `#[allow]` in `quote!`
docs: rust: point directly to the standalone installers
.gitattributes: set diff driver for Rust source code files
rust: upgrade to Rust 1.68.2
rust: arc: fix intra-doc link in `Arc<T>::init`
rust: alloc: clarify what is the upstream version
Diffstat (limited to 'rust/kernel')
-rw-r--r-- | rust/kernel/build_assert.rs | 2 | ||||
-rw-r--r-- | rust/kernel/error.rs | 61 | ||||
-rw-r--r-- | rust/kernel/init.rs | 5 | ||||
-rw-r--r-- | rust/kernel/init/macros.rs | 85 | ||||
-rw-r--r-- | rust/kernel/lib.rs | 4 | ||||
-rw-r--r-- | rust/kernel/std_vendor.rs | 2 | ||||
-rw-r--r-- | rust/kernel/str.rs | 22 | ||||
-rw-r--r-- | rust/kernel/sync/arc.rs | 25 | ||||
-rw-r--r-- | rust/kernel/task.rs | 10 | ||||
-rw-r--r-- | rust/kernel/types.rs | 13 |
10 files changed, 179 insertions, 50 deletions
diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs index 659542393c09..9e37120bc69c 100644 --- a/rust/kernel/build_assert.rs +++ b/rust/kernel/build_assert.rs @@ -67,6 +67,8 @@ macro_rules! build_error { /// assert!(n > 1); // Run-time check /// } /// ``` +/// +/// [`static_assert!`]: crate::static_assert! #[macro_export] macro_rules! build_assert { ($cond:expr $(,)?) => {{ diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 5f4114b30b94..05fcab6abfe6 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -4,16 +4,20 @@ //! //! C header: [`include/uapi/asm-generic/errno-base.h`](../../../include/uapi/asm-generic/errno-base.h) +use crate::str::CStr; + use alloc::{ alloc::{AllocError, LayoutError}, collections::TryReserveError, }; use core::convert::From; +use core::fmt; use core::num::TryFromIntError; use core::str::Utf8Error; /// Contains the C-compatible error codes. +#[rustfmt::skip] pub mod code { macro_rules! declare_err { ($err:tt $(,)? $($doc:expr),+) => { @@ -58,6 +62,25 @@ 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!(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."); + declare_err!(ENOIOCTLCMD, "No ioctl command."); + declare_err!(ERESTART_RESTARTBLOCK, "Restart by calling sys_restart_syscall."); + declare_err!(EPROBE_DEFER, "Driver requests probe retry."); + declare_err!(EOPENSTALE, "Open found a stale dentry."); + declare_err!(ENOPARAM, "Parameter not supported."); + declare_err!(EBADHANDLE, "Illegal NFS file handle."); + declare_err!(ENOTSYNC, "Update synchronization mismatch."); + declare_err!(EBADCOOKIE, "Cookie is stale."); + declare_err!(ENOTSUPP, "Operation is not supported."); + declare_err!(ETOOSMALL, "Buffer or request is too small."); + declare_err!(ESERVERFAULT, "An untranslatable error occurred."); + declare_err!(EBADTYPE, "Type not supported by server."); + declare_err!(EJUKEBOX, "Request initiated, but will not complete before timeout."); + declare_err!(EIOCBQUEUED, "iocb queued, will get completion event."); + declare_err!(ERECALLCONFLICT, "Conflict with recalled state."); + declare_err!(ENOGRACE, "NFS file lock reclaim refused."); } /// Generic integer kernel error. @@ -113,6 +136,42 @@ impl Error { // SAFETY: self.0 is a valid error due to its invariant. unsafe { bindings::ERR_PTR(self.0.into()) as *mut _ } } + + /// Returns a string representing the error, if one exists. + #[cfg(not(testlib))] + pub fn name(&self) -> Option<&'static CStr> { + // SAFETY: Just an FFI call, there are no extra safety requirements. + let ptr = unsafe { bindings::errname(-self.0) }; + if ptr.is_null() { + None + } else { + // SAFETY: The string returned by `errname` is static and `NUL`-terminated. + Some(unsafe { CStr::from_char_ptr(ptr) }) + } + } + + /// Returns a string representing the error, if one exists. + /// + /// When `testlib` is configured, this always returns `None` to avoid the dependency on a + /// kernel function so that tests that use this (e.g., by calling [`Result::unwrap`]) can still + /// run in userspace. + #[cfg(testlib)] + pub fn name(&self) -> Option<&'static CStr> { + None + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.name() { + // Print out number if no name can be found. + None => f.debug_tuple("Error").field(&-self.0).finish(), + // SAFETY: These strings are ASCII-only. + Some(name) => f + .debug_tuple(unsafe { core::str::from_utf8_unchecked(name) }) + .finish(), + } + } } impl From<AllocError> for Error { @@ -177,7 +236,7 @@ impl From<core::convert::Infallible> for Error { /// Note that even if a function does not return anything when it succeeds, /// it should still be modeled as returning a `Result` rather than /// just an [`Error`]. -pub type Result<T = ()> = core::result::Result<T, Error>; +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 /// `Ok(())` otherwise. diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs index 4ebfb08dab11..b4332a4ec1f4 100644 --- a/rust/kernel/init.rs +++ b/rust/kernel/init.rs @@ -197,6 +197,7 @@ //! [`Opaque`]: kernel::types::Opaque //! [`Opaque::ffi_init`]: kernel::types::Opaque::ffi_init //! [`pin_data`]: ::macros::pin_data +//! [`pin_init!`]: crate::pin_init! use crate::{ error::{self, Error}, @@ -255,6 +256,8 @@ pub mod macros; /// 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) => { @@ -804,6 +807,8 @@ macro_rules! try_pin_init { /// /// 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`. #[macro_export] diff --git a/rust/kernel/init/macros.rs b/rust/kernel/init/macros.rs index 541cfad1d8be..00aa4e956c0a 100644 --- a/rust/kernel/init/macros.rs +++ b/rust/kernel/init/macros.rs @@ -16,8 +16,9 @@ //! //! We will look at the following example: //! -//! ```rust +//! ```rust,ignore //! # use kernel::init::*; +//! # use core::pin::Pin; //! #[pin_data] //! #[repr(C)] //! struct Bar<T> { @@ -71,11 +72,12 @@ //! //! Here is the definition of `Bar` from our example: //! -//! ```rust +//! ```rust,ignore //! # use kernel::init::*; //! #[pin_data] //! #[repr(C)] //! struct Bar<T> { +//! #[pin] //! t: T, //! pub x: usize, //! } @@ -83,7 +85,7 @@ //! //! This expands to the following code: //! -//! ```rust +//! ```rust,ignore //! // Firstly the normal definition of the struct, attributes are preserved: //! #[repr(C)] //! struct Bar<T> { @@ -116,20 +118,22 @@ //! unsafe fn t<E>( //! self, //! slot: *mut T, -//! init: impl ::kernel::init::Init<T, E>, +//! // Since `t` is `#[pin]`, this is `PinInit`. +//! init: impl ::kernel::init::PinInit<T, E>, //! ) -> ::core::result::Result<(), E> { -//! unsafe { ::kernel::init::Init::__init(init, slot) } +//! 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 beforehand. +//! // that we constructed above. //! unsafe impl<T> ::kernel::init::__internal::HasPinData for Bar<T> { //! type PinData = __ThePinData<T>; //! unsafe fn __pin_data() -> Self::PinData { @@ -160,6 +164,8 @@ //! 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> @@ -193,7 +199,7 @@ //! //! Here is the impl on `Bar` defining the new function: //! -//! ```rust +//! ```rust,ignore //! impl<T> Bar<T> { //! fn new(t: T) -> impl PinInit<Self> { //! pin_init!(Self { t, x: 0 }) @@ -203,7 +209,7 @@ //! //! This expands to the following code: //! -//! ```rust +//! ```rust,ignore //! impl<T> Bar<T> { //! fn new(t: T) -> impl PinInit<Self> { //! { @@ -232,25 +238,31 @@ //! // 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(&raw mut (*slot).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 it fails. This -//! // `DropGuard` will drop the field when it gets dropped and has not yet -//! // been forgotten. We make a reference to it, so users cannot `mem::forget` -//! // it from the initializer, since the name is the same as the field. +//! // 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. We make a reference to it, so users +//! // cannot `mem::forget` it from the initializer, since the name is the same +//! // as the field (including hygiene). //! let t = &unsafe { -//! ::kernel::init::__internal::DropGuard::new(&raw mut (*slot).t) +//! ::kernel::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(&raw mut (*slot).x, x) }; +//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) }; +//! // We again create a `DropGuard`. //! let x = &unsafe { -//! ::kernel::init::__internal::DropGuard::new(&raw mut (*slot).x) +//! ::kernel::init::__internal::DropGuard::new( +//! ::core::addr_of_mut!((*slot).x), +//! ) //! }; //! -//! // Here we use the type checker to ensuer that every field has been +//! // 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 @@ -272,7 +284,7 @@ //! }; //! } //! // Since initialization has successfully completed, we can now forget the -//! // guards. +//! // guards. This is not `mem::forget`, since we only have `&DropGuard`. //! unsafe { ::kernel::init::__internal::DropGuard::forget(t) }; //! unsafe { ::kernel::init::__internal::DropGuard::forget(x) }; //! } @@ -280,7 +292,7 @@ //! // `__InitOk` that we need to return. //! Ok(__InitOk) //! }); -//! // Change the return type of the closure. +//! // Change the return type from `__InitOk` to `()`. //! let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> { //! init(slot).map(|__InitOk| ()) //! }; @@ -299,7 +311,7 @@ //! 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 +//! ```rust,ignore //! #[pin_data(PinnedDrop)] //! struct Foo { //! a: usize, @@ -310,7 +322,7 @@ //! //! This expands to the following code: //! -//! ```rust +//! ```rust,ignore //! struct Foo { //! a: usize, //! b: Bar<u32>, @@ -330,8 +342,6 @@ //! unsafe fn b<E>( //! self, //! slot: *mut Bar<u32>, -//! // Note that this is `PinInit` instead of `Init`, this is because `b` is -//! // structurally pinned, as marked by the `#[pin]` attribute. //! init: impl ::kernel::init::PinInit<Bar<u32>, E>, //! ) -> ::core::result::Result<(), E> { //! unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) } @@ -359,14 +369,13 @@ //! struct __Unpin<'__pin> { //! __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>, //! __phantom: ::core::marker::PhantomData<fn(Foo) -> Foo>, -//! // Since this field is `#[pin]`, it is listed here. //! 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 it here and delegate to `PinnedDrop`. +//! // 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 @@ -388,7 +397,7 @@ //! //! Here is the `PinnedDrop` impl for `Foo`: //! -//! ```rust +//! ```rust,ignore //! #[pinned_drop] //! impl PinnedDrop for Foo { //! fn drop(self: Pin<&mut Self>) { @@ -399,7 +408,7 @@ //! //! This expands to the following code: //! -//! ```rust +//! ```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) { @@ -410,10 +419,10 @@ //! //! ## `pin_init!` on `Foo` //! -//! Since we already took a look at `pin_init!` on `Bar`, this section will only explain the -//! differences/new things in the expansion of `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 +//! ```rust,ignore //! let a = 42; //! let initializer = pin_init!(Foo { //! a, @@ -423,7 +432,7 @@ //! //! This expands to the following code: //! -//! ```rust +//! ```rust,ignore //! let a = 42; //! let initializer = { //! struct __InitOk; @@ -438,13 +447,15 @@ //! >(data, move |slot| { //! { //! struct __InitOk; -//! unsafe { ::core::ptr::write(&raw mut (*slot).a, a) }; -//! let a = &unsafe { ::kernel::init::__internal::DropGuard::new(&raw mut (*slot).a) }; +//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) }; +//! let a = &unsafe { +//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a)) +//! }; //! let b = Bar::new(36); -//! // Here we use `data` to access the correct field and require that `b` is of type -//! // `PinInit<Bar<u32>, Infallible>`. -//! unsafe { data.b(&raw mut (*slot).b, b)? }; -//! let b = &unsafe { ::kernel::init::__internal::DropGuard::new(&raw mut (*slot).b) }; +//! unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? }; +//! let b = &unsafe { +//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b)) +//! }; //! //! #[allow(unreachable_code, clippy::diverging_sub_expression)] //! if false { diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 676995d4e460..85b261209977 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -14,12 +14,8 @@ #![no_std] #![feature(allocator_api)] #![feature(coerce_unsized)] -#![feature(core_ffi_c)] #![feature(dispatch_from_dyn)] -#![feature(explicit_generic_args_with_impl_trait)] -#![feature(generic_associated_types)] #![feature(new_uninit)] -#![feature(pin_macro)] #![feature(receiver_trait)] #![feature(unsize)] diff --git a/rust/kernel/std_vendor.rs b/rust/kernel/std_vendor.rs index b3e68b24a8c6..388d6a5147a2 100644 --- a/rust/kernel/std_vendor.rs +++ b/rust/kernel/std_vendor.rs @@ -137,6 +137,8 @@ /// [`std::dbg`]: https://doc.rust-lang.org/std/macro.dbg.html /// [`eprintln`]: https://doc.rust-lang.org/std/macro.eprintln.html /// [`printk`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html +/// [`pr_info`]: crate::pr_info! +/// [`pr_debug`]: crate::pr_debug! #[macro_export] macro_rules! dbg { // NOTE: We cannot use `concat!` to make a static string as a format argument diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index cd3d2a6cf1fc..c9dd3bf59e34 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -2,6 +2,7 @@ //! String representations. +use alloc::alloc::AllocError; use alloc::vec::Vec; use core::fmt::{self, Write}; use core::ops::{self, Deref, Index}; @@ -199,6 +200,12 @@ impl CStr { pub unsafe fn as_str_unchecked(&self) -> &str { unsafe { core::str::from_utf8_unchecked(self.as_bytes()) } } + + /// Convert this [`CStr`] into a [`CString`] by allocating memory and + /// copying over the string data. + pub fn to_cstring(&self) -> Result<CString, AllocError> { + CString::try_from(self) + } } impl fmt::Display for CStr { @@ -584,6 +591,21 @@ impl Deref for CString { } } +impl<'a> TryFrom<&'a CStr> for CString { + type Error = AllocError; + + fn try_from(cstr: &'a CStr) -> Result<CString, AllocError> { + let mut buf = Vec::new(); + + buf.try_extend_from_slice(cstr.as_bytes_with_nul()) + .map_err(|_| AllocError)?; + + // INVARIANT: The `CStr` and `CString` types have the same invariants for + // the string data, and we copied it over without changes. + Ok(CString { buf }) + } +} + /// A convenience alias for [`core::format_args`]. #[macro_export] macro_rules! fmt { diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index e6d206242465..a89843cacaad 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -146,13 +146,15 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Ar // SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because // it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs -// `T` to be `Send` because any thread that has an `Arc<T>` may ultimately access `T` directly, for -// example, when the reference count reaches zero and `T` is dropped. +// `T` to be `Send` because any thread that has an `Arc<T>` may ultimately access `T` using a +// mutable reference when the reference count reaches zero and `T` is dropped. unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {} -// SAFETY: It is safe to send `&Arc<T>` to another thread when the underlying `T` is `Sync` for the -// same reason as above. `T` needs to be `Send` as well because a thread can clone an `&Arc<T>` -// into an `Arc<T>`, which may lead to `T` being accessed by the same reasoning as above. +// SAFETY: It is safe to send `&Arc<T>` to another thread when the underlying `T` is `Sync` +// because it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, +// it needs `T` to be `Send` because any thread that has a `&Arc<T>` may clone it and get an +// `Arc<T>` on that thread, so the thread may ultimately access `T` using a mutable reference when +// the reference count reaches zero and `T` is dropped. unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {} impl<T> Arc<T> { @@ -185,7 +187,7 @@ impl<T> Arc<T> { /// Use the given initializer to in-place initialize a `T`. /// - /// This is equivalent to [`pin_init`], since an [`Arc`] is always pinned. + /// This is equivalent to [`Arc<T>::pin_init`], since an [`Arc`] is always pinned. #[inline] pub fn init<E>(init: impl Init<T, E>) -> error::Result<Self> where @@ -221,6 +223,11 @@ impl<T: ?Sized> Arc<T> { // reference can be created. unsafe { ArcBorrow::new(self.ptr) } } + + /// Compare whether two [`Arc`] pointers reference the same underlying object. + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + core::ptr::eq(this.ptr.as_ptr(), other.ptr.as_ptr()) + } } impl<T: 'static> ForeignOwnable for Arc<T> { @@ -259,6 +266,12 @@ impl<T: ?Sized> Deref for Arc<T> { } } +impl<T: ?Sized> AsRef<T> for Arc<T> { + fn as_ref(&self) -> &T { + self.deref() + } +} + impl<T: ?Sized> Clone for Arc<T> { fn clone(&self) -> Self { // INVARIANT: C `refcount_inc` saturates the refcount, so it cannot overflow to zero. diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index 526d29a0ae27..7eda15e5f1b3 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -64,8 +64,14 @@ macro_rules! current { #[repr(transparent)] pub struct Task(pub(crate) Opaque<bindings::task_struct>); -// SAFETY: It's OK to access `Task` through references from other threads because we're either -// accessing properties that don't change (e.g., `pid`, `group_leader`) or that are properly +// SAFETY: By design, the only way to access a `Task` is via the `current` function or via an +// `ARef<Task>` obtained through the `AlwaysRefCounted` impl. This means that the only situation in +// which a `Task` can be accessed mutably is when the refcount drops to zero and the destructor +// runs. It is safe for that to happen on any thread, so it is ok for this type to be `Send`. +unsafe impl Send for Task {} + +// SAFETY: It's OK to access `Task` through shared references from other threads because we're +// either accessing properties that don't change (e.g., `pid`, `group_leader`) or that are properly // synchronised by C code (e.g., `signal_pending`). unsafe impl Sync for Task {} diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 29db59d6119a..1e5380b16ed5 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -321,6 +321,19 @@ pub struct ARef<T: AlwaysRefCounted> { _p: PhantomData<T>, } +// SAFETY: It is safe to send `ARef<T>` to another thread when the underlying `T` is `Sync` because +// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs +// `T` to be `Send` because any thread that has an `ARef<T>` may ultimately access `T` using a +// mutable reference, for example, when the reference count reaches zero and `T` is dropped. +unsafe impl<T: AlwaysRefCounted + Sync + Send> Send for ARef<T> {} + +// SAFETY: It is safe to send `&ARef<T>` to another thread when the underlying `T` is `Sync` +// because it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, +// it needs `T` to be `Send` because any thread that has a `&ARef<T>` may clone it and get an +// `ARef<T>` on that thread, so the thread may ultimately access `T` using a mutable reference, for +// example, when the reference count reaches zero and `T` is dropped. +unsafe impl<T: AlwaysRefCounted + Sync + Send> Sync for ARef<T> {} + impl<T: AlwaysRefCounted> ARef<T> { /// Creates a new instance of [`ARef`]. /// |