mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 12:14:10 +08:00
Rust changes for v6.3
More core additions, getting closer to a point where the first Rust modules can be upstreamed. The major ones being: - Sync: new types 'Arc', 'ArcBorrow' and 'UniqueArc'. - Types: new trait 'ForeignOwnable' and new type 'ScopeGuard'. There is also a substantial removal in terms of lines: - 'alloc' crate: remove the 'borrow' module (type 'Cow' and trait 'ToOwned'). -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEPjU5OPd5QIZ9jqqOGXyLc2htIW0FAmPpKj4ACgkQGXyLc2ht IW1AzA//TiKlip9/+kli+ZgFiqqrJGJVMg5EsBAjW7/LP3rPryqmA2MQWHFbEPWC OzV99XZlELcsmp6JeREssuGThm4j6xBk0EsZ0tPtq4S0cPaMChVTaeRlXoMv3ahs i5jIpJYHrZz28zmrQ0L6QZSexTRU+85btcx8C4cDp+b2AGmL7CEepGvHsHMt36GC Joi9L2zqB6u6cNNX4Rm5oD3T4++bUWR8bwrHeng2oO0BWZd8GCqAXUjmVPa0Dkss X8NucPsP8OuQo7lIsF6lKH7hXT/y+OpJBFGS5U7huAMsFV807vuuJVK4uSAUWfji b1M4Bo1dDC4kX4a2atmzmXmn8m8/HT4QwWCBWunMtg/02jztJgUy9mUkZm1ZMt7/ sZRi6WF0HCQeTrQhCS6MGLbZt/ifHhH/bz7Fg5hbNUz9RY5Ydaz9GBrIeA8kqEtM BmDTqmsjerJIic429DAKTVtUFYxh8WJyMCNtVbC2z8JAcXShGL8zBZVBLzKpu7dy SskhYzkViCvkGvryHYiMhEkzNgpi+whD/e4eoWJmwCMOAPaZokpT7C3cmp0xWCuy 4V5PoyMHTKPqPNYUjKsjDq5hTRLV9OPNbJyNhZeEPr24NnxLxE4DCT5vsidHStNR Vx+B8Y5Xuk/gfZjaEd1m5keBwGfBwDrVpQyjBWYnVJWO2lWnD+Y= =Ora4 -----END PGP SIGNATURE----- Merge tag 'rust-6.3' of https://github.com/Rust-for-Linux/linux Pull Rust updates from Miguel Ojeda: "More core additions, getting closer to a point where the first Rust modules can be upstreamed. The major ones being: - Sync: new types 'Arc', 'ArcBorrow' and 'UniqueArc'. - Types: new trait 'ForeignOwnable' and new type 'ScopeGuard'. There is also a substantial removal in terms of lines: - 'alloc' crate: remove the 'borrow' module (type 'Cow' and trait 'ToOwned')" * tag 'rust-6.3' of https://github.com/Rust-for-Linux/linux: rust: delete rust-project.json when running make clean rust: MAINTAINERS: Add the zulip link rust: types: implement `ForeignOwnable` for `Arc<T>` rust: types: implement `ForeignOwnable` for the unit type rust: types: implement `ForeignOwnable` for `Box<T>` rust: types: introduce `ForeignOwnable` rust: types: introduce `ScopeGuard` rust: prelude: prevent doc inline of external imports rust: sync: add support for dispatching on Arc and ArcBorrow. rust: sync: introduce `UniqueArc` rust: sync: allow type of `self` to be `ArcBorrow<T>` rust: sync: introduce `ArcBorrow` rust: sync: allow coercion from `Arc<T>` to `Arc<U>` rust: sync: allow type of `self` to be `Arc<T>` or variants rust: sync: add `Arc` for ref-counted allocations rust: compiler_builtins: make stubs non-global rust: alloc: remove the `borrow` module (`ToOwned`, `Cow`)
This commit is contained in:
commit
69adb0bcb8
@ -18234,6 +18234,7 @@ L: rust-for-linux@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://github.com/Rust-for-Linux/linux
|
||||
B: https://github.com/Rust-for-Linux/linux/issues
|
||||
C: zulip://rust-for-linux.zulipchat.com
|
||||
T: git https://github.com/Rust-for-Linux/linux.git rust-next
|
||||
F: Documentation/rust/
|
||||
F: rust/
|
||||
|
2
Makefile
2
Makefile
@ -1602,7 +1602,7 @@ endif # CONFIG_MODULES
|
||||
CLEAN_FILES += include/ksym vmlinux.symvers modules-only.symvers \
|
||||
modules.builtin modules.builtin.modinfo modules.nsdeps \
|
||||
compile_commands.json .thinlto-cache rust/test rust/doc \
|
||||
.vmlinux.objs .vmlinux.export.c
|
||||
rust-project.json .vmlinux.objs .vmlinux.export.c
|
||||
|
||||
# Directories & files removed with 'make mrproper'
|
||||
MRPROPER_FILES += include/config include/generated \
|
||||
|
@ -50,6 +50,7 @@ core-cfgs = \
|
||||
--cfg no_fp_fmt_parse
|
||||
|
||||
alloc-cfgs = \
|
||||
--cfg no_borrow \
|
||||
--cfg no_fmt \
|
||||
--cfg no_global_oom_handling \
|
||||
--cfg no_macros \
|
||||
@ -359,8 +360,22 @@ rust-analyzer:
|
||||
$(Q)$(srctree)/scripts/generate_rust_analyzer.py $(srctree) $(objtree) \
|
||||
$(RUST_LIB_SRC) > $(objtree)/rust-project.json
|
||||
|
||||
redirect-intrinsics = \
|
||||
__eqsf2 __gesf2 __lesf2 __nesf2 __unordsf2 \
|
||||
__unorddf2 \
|
||||
__muloti4 __multi3 \
|
||||
__udivmodti4 __udivti3 __umodti3
|
||||
|
||||
ifneq ($(or $(CONFIG_ARM64),$(and $(CONFIG_RISCV),$(CONFIG_64BIT))),)
|
||||
# These intrinsics are defined for ARM64 and RISCV64
|
||||
redirect-intrinsics += \
|
||||
__ashrti3 \
|
||||
__ashlti3 __lshrti3
|
||||
endif
|
||||
|
||||
$(obj)/core.o: private skip_clippy = 1
|
||||
$(obj)/core.o: private skip_flags = -Dunreachable_pub
|
||||
$(obj)/core.o: private rustc_objcopy = $(foreach sym,$(redirect-intrinsics),--redefine-sym $(sym)=__rust$(sym))
|
||||
$(obj)/core.o: private rustc_target_flags = $(core-cfgs)
|
||||
$(obj)/core.o: $(RUST_LIB_SRC)/core/src/lib.rs $(obj)/target.json FORCE
|
||||
$(call if_changed_dep,rustc_library)
|
||||
|
@ -1,498 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
|
||||
//! A module for working with borrowed data.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use core::cmp::Ordering;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::ops::Deref;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::ops::{Add, AddAssign};
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::borrow::{Borrow, BorrowMut};
|
||||
|
||||
use core::fmt;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use crate::string::String;
|
||||
|
||||
use Cow::*;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B>
|
||||
where
|
||||
B: ToOwned,
|
||||
<B as ToOwned>::Owned: 'a,
|
||||
{
|
||||
fn borrow(&self) -> &B {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
/// A generalization of `Clone` to borrowed data.
|
||||
///
|
||||
/// Some types make it possible to go from borrowed to owned, usually by
|
||||
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
|
||||
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
|
||||
/// from any borrow of a given type.
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "ToOwned")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait ToOwned {
|
||||
/// The resulting type after obtaining ownership.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
type Owned: Borrow<Self>;
|
||||
|
||||
/// Creates owned data from borrowed data, usually by cloning.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let s: &str = "a";
|
||||
/// let ss: String = s.to_owned();
|
||||
///
|
||||
/// let v: &[i32] = &[1, 2];
|
||||
/// let vv: Vec<i32> = v.to_owned();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "cloning is often expensive and is not expected to have side effects"]
|
||||
fn to_owned(&self) -> Self::Owned;
|
||||
|
||||
/// Uses borrowed data to replace owned data, usually by cloning.
|
||||
///
|
||||
/// This is borrow-generalized version of `Clone::clone_from`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(toowned_clone_into)]
|
||||
/// let mut s: String = String::new();
|
||||
/// "hello".clone_into(&mut s);
|
||||
///
|
||||
/// let mut v: Vec<i32> = Vec::new();
|
||||
/// [1, 2][..].clone_into(&mut v);
|
||||
/// ```
|
||||
#[unstable(feature = "toowned_clone_into", reason = "recently added", issue = "41263")]
|
||||
fn clone_into(&self, target: &mut Self::Owned) {
|
||||
*target = self.to_owned();
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> ToOwned for T
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
type Owned = T;
|
||||
fn to_owned(&self) -> T {
|
||||
self.clone()
|
||||
}
|
||||
|
||||
fn clone_into(&self, target: &mut T) {
|
||||
target.clone_from(self);
|
||||
}
|
||||
}
|
||||
|
||||
/// A clone-on-write smart pointer.
|
||||
///
|
||||
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
|
||||
/// can enclose and provide immutable access to borrowed data, and clone the
|
||||
/// data lazily when mutation or ownership is required. The type is designed to
|
||||
/// work with general borrowed data via the `Borrow` trait.
|
||||
///
|
||||
/// `Cow` implements `Deref`, which means that you can call
|
||||
/// non-mutating methods directly on the data it encloses. If mutation
|
||||
/// is desired, `to_mut` will obtain a mutable reference to an owned
|
||||
/// value, cloning if necessary.
|
||||
///
|
||||
/// If you need reference-counting pointers, note that
|
||||
/// [`Rc::make_mut`][crate::rc::Rc::make_mut] and
|
||||
/// [`Arc::make_mut`][crate::sync::Arc::make_mut] can provide clone-on-write
|
||||
/// functionality as well.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::borrow::Cow;
|
||||
///
|
||||
/// fn abs_all(input: &mut Cow<[i32]>) {
|
||||
/// for i in 0..input.len() {
|
||||
/// let v = input[i];
|
||||
/// if v < 0 {
|
||||
/// // Clones into a vector if not already owned.
|
||||
/// input.to_mut()[i] = -v;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // No clone occurs because `input` doesn't need to be mutated.
|
||||
/// let slice = [0, 1, 2];
|
||||
/// let mut input = Cow::from(&slice[..]);
|
||||
/// abs_all(&mut input);
|
||||
///
|
||||
/// // Clone occurs because `input` needs to be mutated.
|
||||
/// let slice = [-1, 0, 1];
|
||||
/// let mut input = Cow::from(&slice[..]);
|
||||
/// abs_all(&mut input);
|
||||
///
|
||||
/// // No clone occurs because `input` is already owned.
|
||||
/// let mut input = Cow::from(vec![-1, 0, 1]);
|
||||
/// abs_all(&mut input);
|
||||
/// ```
|
||||
///
|
||||
/// Another example showing how to keep `Cow` in a struct:
|
||||
///
|
||||
/// ```
|
||||
/// use std::borrow::Cow;
|
||||
///
|
||||
/// struct Items<'a, X: 'a> where [X]: ToOwned<Owned = Vec<X>> {
|
||||
/// values: Cow<'a, [X]>,
|
||||
/// }
|
||||
///
|
||||
/// impl<'a, X: Clone + 'a> Items<'a, X> where [X]: ToOwned<Owned = Vec<X>> {
|
||||
/// fn new(v: Cow<'a, [X]>) -> Self {
|
||||
/// Items { values: v }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // Creates a container from borrowed values of a slice
|
||||
/// let readonly = [1, 2];
|
||||
/// let borrowed = Items::new((&readonly[..]).into());
|
||||
/// match borrowed {
|
||||
/// Items { values: Cow::Borrowed(b) } => println!("borrowed {b:?}"),
|
||||
/// _ => panic!("expect borrowed value"),
|
||||
/// }
|
||||
///
|
||||
/// let mut clone_on_write = borrowed;
|
||||
/// // Mutates the data from slice into owned vec and pushes a new value on top
|
||||
/// clone_on_write.values.to_mut().push(3);
|
||||
/// println!("clone_on_write = {:?}", clone_on_write.values);
|
||||
///
|
||||
/// // The data was mutated. Let's check it out.
|
||||
/// match clone_on_write {
|
||||
/// Items { values: Cow::Owned(_) } => println!("clone_on_write contains owned data"),
|
||||
/// _ => panic!("expect owned data"),
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "Cow")]
|
||||
pub enum Cow<'a, B: ?Sized + 'a>
|
||||
where
|
||||
B: ToOwned,
|
||||
{
|
||||
/// Borrowed data.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B),
|
||||
|
||||
/// Owned data.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Owned(#[stable(feature = "rust1", since = "1.0.0")] <B as ToOwned>::Owned),
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B: ?Sized + ToOwned> Clone for Cow<'_, B> {
|
||||
fn clone(&self) -> Self {
|
||||
match *self {
|
||||
Borrowed(b) => Borrowed(b),
|
||||
Owned(ref o) => {
|
||||
let b: &B = o.borrow();
|
||||
Owned(b.to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_from(&mut self, source: &Self) {
|
||||
match (self, source) {
|
||||
(&mut Owned(ref mut dest), &Owned(ref o)) => o.borrow().clone_into(dest),
|
||||
(t, s) => *t = s.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: ?Sized + ToOwned> Cow<'_, B> {
|
||||
/// Returns true if the data is borrowed, i.e. if `to_mut` would require additional work.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(cow_is_borrowed)]
|
||||
/// use std::borrow::Cow;
|
||||
///
|
||||
/// let cow = Cow::Borrowed("moo");
|
||||
/// assert!(cow.is_borrowed());
|
||||
///
|
||||
/// let bull: Cow<'_, str> = Cow::Owned("...moo?".to_string());
|
||||
/// assert!(!bull.is_borrowed());
|
||||
/// ```
|
||||
#[unstable(feature = "cow_is_borrowed", issue = "65143")]
|
||||
#[rustc_const_unstable(feature = "const_cow_is_borrowed", issue = "65143")]
|
||||
pub const fn is_borrowed(&self) -> bool {
|
||||
match *self {
|
||||
Borrowed(_) => true,
|
||||
Owned(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the data is owned, i.e. if `to_mut` would be a no-op.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(cow_is_borrowed)]
|
||||
/// use std::borrow::Cow;
|
||||
///
|
||||
/// let cow: Cow<'_, str> = Cow::Owned("moo".to_string());
|
||||
/// assert!(cow.is_owned());
|
||||
///
|
||||
/// let bull = Cow::Borrowed("...moo?");
|
||||
/// assert!(!bull.is_owned());
|
||||
/// ```
|
||||
#[unstable(feature = "cow_is_borrowed", issue = "65143")]
|
||||
#[rustc_const_unstable(feature = "const_cow_is_borrowed", issue = "65143")]
|
||||
pub const fn is_owned(&self) -> bool {
|
||||
!self.is_borrowed()
|
||||
}
|
||||
|
||||
/// Acquires a mutable reference to the owned form of the data.
|
||||
///
|
||||
/// Clones the data if it is not already owned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::borrow::Cow;
|
||||
///
|
||||
/// let mut cow = Cow::Borrowed("foo");
|
||||
/// cow.to_mut().make_ascii_uppercase();
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// cow,
|
||||
/// Cow::Owned(String::from("FOO")) as Cow<str>
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
|
||||
match *self {
|
||||
Borrowed(borrowed) => {
|
||||
*self = Owned(borrowed.to_owned());
|
||||
match *self {
|
||||
Borrowed(..) => unreachable!(),
|
||||
Owned(ref mut owned) => owned,
|
||||
}
|
||||
}
|
||||
Owned(ref mut owned) => owned,
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts the owned data.
|
||||
///
|
||||
/// Clones the data if it is not already owned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Calling `into_owned` on a `Cow::Borrowed` returns a clone of the borrowed data:
|
||||
///
|
||||
/// ```
|
||||
/// use std::borrow::Cow;
|
||||
///
|
||||
/// let s = "Hello world!";
|
||||
/// let cow = Cow::Borrowed(s);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// cow.into_owned(),
|
||||
/// String::from(s)
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// Calling `into_owned` on a `Cow::Owned` returns the owned data. The data is moved out of the
|
||||
/// `Cow` without being cloned.
|
||||
///
|
||||
/// ```
|
||||
/// use std::borrow::Cow;
|
||||
///
|
||||
/// let s = "Hello world!";
|
||||
/// let cow: Cow<str> = Cow::Owned(String::from(s));
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// cow.into_owned(),
|
||||
/// String::from(s)
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_owned(self) -> <B as ToOwned>::Owned {
|
||||
match self {
|
||||
Borrowed(borrowed) => borrowed.to_owned(),
|
||||
Owned(owned) => owned,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
||||
impl<B: ?Sized + ToOwned> const Deref for Cow<'_, B>
|
||||
where
|
||||
B::Owned: ~const Borrow<B>,
|
||||
{
|
||||
type Target = B;
|
||||
|
||||
fn deref(&self) -> &B {
|
||||
match *self {
|
||||
Borrowed(borrowed) => borrowed,
|
||||
Owned(ref owned) => owned.borrow(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B: ?Sized> Eq for Cow<'_, B> where B: Eq + ToOwned {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B: ?Sized> Ord for Cow<'_, B>
|
||||
where
|
||||
B: Ord + ToOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
Ord::cmp(&**self, &**other)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B>
|
||||
where
|
||||
B: PartialEq<C> + ToOwned,
|
||||
C: ToOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Cow<'b, C>) -> bool {
|
||||
PartialEq::eq(&**self, &**other)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B>
|
||||
where
|
||||
B: PartialOrd + ToOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
|
||||
PartialOrd::partial_cmp(&**self, &**other)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B: ?Sized> fmt::Debug for Cow<'_, B>
|
||||
where
|
||||
B: fmt::Debug + ToOwned<Owned: fmt::Debug>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
Borrowed(ref b) => fmt::Debug::fmt(b, f),
|
||||
Owned(ref o) => fmt::Debug::fmt(o, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B: ?Sized> fmt::Display for Cow<'_, B>
|
||||
where
|
||||
B: fmt::Display + ToOwned<Owned: fmt::Display>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
Borrowed(ref b) => fmt::Display::fmt(b, f),
|
||||
Owned(ref o) => fmt::Display::fmt(o, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "default", since = "1.11.0")]
|
||||
impl<B: ?Sized> Default for Cow<'_, B>
|
||||
where
|
||||
B: ToOwned<Owned: Default>,
|
||||
{
|
||||
/// Creates an owned Cow<'a, B> with the default value for the contained owned value.
|
||||
fn default() -> Self {
|
||||
Owned(<B as ToOwned>::Owned::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B: ?Sized> Hash for Cow<'_, B>
|
||||
where
|
||||
B: Hash + ToOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
Hash::hash(&**self, state)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + ToOwned> AsRef<T> for Cow<'_, T> {
|
||||
fn as_ref(&self) -> &T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "cow_add", since = "1.14.0")]
|
||||
impl<'a> Add<&'a str> for Cow<'a, str> {
|
||||
type Output = Cow<'a, str>;
|
||||
|
||||
#[inline]
|
||||
fn add(mut self, rhs: &'a str) -> Self::Output {
|
||||
self += rhs;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "cow_add", since = "1.14.0")]
|
||||
impl<'a> Add<Cow<'a, str>> for Cow<'a, str> {
|
||||
type Output = Cow<'a, str>;
|
||||
|
||||
#[inline]
|
||||
fn add(mut self, rhs: Cow<'a, str>) -> Self::Output {
|
||||
self += rhs;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "cow_add", since = "1.14.0")]
|
||||
impl<'a> AddAssign<&'a str> for Cow<'a, str> {
|
||||
fn add_assign(&mut self, rhs: &'a str) {
|
||||
if self.is_empty() {
|
||||
*self = Cow::Borrowed(rhs)
|
||||
} else if !rhs.is_empty() {
|
||||
if let Cow::Borrowed(lhs) = *self {
|
||||
let mut s = String::with_capacity(lhs.len() + rhs.len());
|
||||
s.push_str(lhs);
|
||||
*self = Cow::Owned(s);
|
||||
}
|
||||
self.to_mut().push_str(rhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "cow_add", since = "1.14.0")]
|
||||
impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> {
|
||||
fn add_assign(&mut self, rhs: Cow<'a, str>) {
|
||||
if self.is_empty() {
|
||||
*self = rhs
|
||||
} else if !rhs.is_empty() {
|
||||
if let Cow::Borrowed(lhs) = *self {
|
||||
let mut s = String::with_capacity(lhs.len() + rhs.len());
|
||||
s.push_str(lhs);
|
||||
*self = Cow::Owned(s);
|
||||
}
|
||||
self.to_mut().push_str(&rhs);
|
||||
}
|
||||
}
|
||||
}
|
@ -100,7 +100,7 @@
|
||||
#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))]
|
||||
#![feature(const_box)]
|
||||
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))]
|
||||
#![feature(const_cow_is_borrowed)]
|
||||
#![cfg_attr(not(no_borrow), feature(const_cow_is_borrowed))]
|
||||
#![feature(const_convert)]
|
||||
#![feature(const_size_of_val)]
|
||||
#![feature(const_align_of_val)]
|
||||
@ -215,6 +215,7 @@ pub mod boxed;
|
||||
mod boxed {
|
||||
pub use std::boxed::Box;
|
||||
}
|
||||
#[cfg(not(no_borrow))]
|
||||
pub mod borrow;
|
||||
pub mod collections;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
|
@ -72,6 +72,7 @@ use core::ptr::{self, NonNull};
|
||||
use core::slice::{self, SliceIndex};
|
||||
|
||||
use crate::alloc::{Allocator, Global};
|
||||
#[cfg(not(no_borrow))]
|
||||
use crate::borrow::{Cow, ToOwned};
|
||||
use crate::boxed::Box;
|
||||
use crate::collections::TryReserveError;
|
||||
@ -94,6 +95,7 @@ pub use self::drain::Drain;
|
||||
|
||||
mod drain;
|
||||
|
||||
#[cfg(not(no_borrow))]
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
mod cow;
|
||||
|
||||
@ -3103,6 +3105,7 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_borrow))]
|
||||
#[stable(feature = "vec_from_cow_slice", since = "1.14.0")]
|
||||
impl<'a, T> From<Cow<'a, [T]>> for Vec<T>
|
||||
where
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/refcount.h>
|
||||
|
||||
/* `bindgen` gets confused at certain things. */
|
||||
const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL;
|
||||
|
@ -41,6 +41,7 @@ mod bindings_raw {
|
||||
#[allow(dead_code)]
|
||||
mod bindings_helper {
|
||||
// Import the generated bindings for types.
|
||||
use super::bindings_raw::*;
|
||||
include!(concat!(
|
||||
env!("OBJTREE"),
|
||||
"/rust/bindings/bindings_helpers_generated.rs"
|
||||
|
@ -28,7 +28,7 @@ macro_rules! define_panicking_intrinsics(
|
||||
($reason: tt, { $($ident: ident, )* }) => {
|
||||
$(
|
||||
#[doc(hidden)]
|
||||
#[no_mangle]
|
||||
#[export_name = concat!("__rust", stringify!($ident))]
|
||||
pub extern "C" fn $ident() {
|
||||
panic!($reason);
|
||||
}
|
||||
@ -61,3 +61,6 @@ define_panicking_intrinsics!("`u128` should not be used", {
|
||||
__udivti3,
|
||||
__umodti3,
|
||||
});
|
||||
|
||||
// NOTE: if you are adding a new intrinsic here, you should also add it to
|
||||
// `redirect-intrinsics` in `rust/Makefile`.
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/build_bug.h>
|
||||
#include <linux/refcount.h>
|
||||
|
||||
__noreturn void rust_helper_BUG(void)
|
||||
{
|
||||
@ -27,6 +28,24 @@ __noreturn void rust_helper_BUG(void)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rust_helper_BUG);
|
||||
|
||||
refcount_t rust_helper_REFCOUNT_INIT(int n)
|
||||
{
|
||||
return (refcount_t)REFCOUNT_INIT(n);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rust_helper_REFCOUNT_INIT);
|
||||
|
||||
void rust_helper_refcount_inc(refcount_t *r)
|
||||
{
|
||||
refcount_inc(r);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rust_helper_refcount_inc);
|
||||
|
||||
bool rust_helper_refcount_dec_and_test(refcount_t *r)
|
||||
{
|
||||
return refcount_dec_and_test(r);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rust_helper_refcount_dec_and_test);
|
||||
|
||||
/*
|
||||
* We use `bindgen`'s `--size_t-is-usize` option to bind the C `size_t` type
|
||||
* as the Rust `usize` type, so we can use it in contexts where Rust
|
||||
|
@ -13,7 +13,12 @@
|
||||
|
||||
#![no_std]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(coerce_unsized)]
|
||||
#![feature(core_ffi_c)]
|
||||
#![feature(dispatch_from_dyn)]
|
||||
#![feature(generic_associated_types)]
|
||||
#![feature(receiver_trait)]
|
||||
#![feature(unsize)]
|
||||
|
||||
// Ensure conditional compilation based on the kernel configuration works;
|
||||
// otherwise we may silently break things like initcall handling.
|
||||
@ -31,6 +36,7 @@ mod static_assert;
|
||||
#[doc(hidden)]
|
||||
pub mod std_vendor;
|
||||
pub mod str;
|
||||
pub mod sync;
|
||||
pub mod types;
|
||||
|
||||
#[doc(hidden)]
|
||||
|
@ -11,15 +11,21 @@
|
||||
//! use kernel::prelude::*;
|
||||
//! ```
|
||||
|
||||
#[doc(no_inline)]
|
||||
pub use core::pin::Pin;
|
||||
|
||||
#[doc(no_inline)]
|
||||
pub use alloc::{boxed::Box, vec::Vec};
|
||||
|
||||
#[doc(no_inline)]
|
||||
pub use macros::{module, vtable};
|
||||
|
||||
pub use super::build_assert;
|
||||
|
||||
pub use super::{dbg, pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
|
||||
// `super::std_vendor` is hidden, which makes the macro inline for some reason.
|
||||
#[doc(no_inline)]
|
||||
pub use super::dbg;
|
||||
pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
|
||||
|
||||
pub use super::static_assert;
|
||||
|
||||
|
10
rust/kernel/sync.rs
Normal file
10
rust/kernel/sync.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
//! Synchronisation primitives.
|
||||
//!
|
||||
//! This module contains the kernel APIs related to synchronisation that have been ported or
|
||||
//! wrapped for usage by Rust code in the kernel.
|
||||
|
||||
mod arc;
|
||||
|
||||
pub use arc::{Arc, ArcBorrow, UniqueArc};
|
524
rust/kernel/sync/arc.rs
Normal file
524
rust/kernel/sync/arc.rs
Normal file
@ -0,0 +1,524 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
//! A reference-counted pointer.
|
||||
//!
|
||||
//! This module implements a way for users to create reference-counted objects and pointers to
|
||||
//! them. Such a pointer automatically increments and decrements the count, and drops the
|
||||
//! underlying object when it reaches zero. It is also safe to use concurrently from multiple
|
||||
//! threads.
|
||||
//!
|
||||
//! It is different from the standard library's [`Arc`] in a few ways:
|
||||
//! 1. It is backed by the kernel's `refcount_t` type.
|
||||
//! 2. It does not support weak references, which allows it to be half the size.
|
||||
//! 3. It saturates the reference count instead of aborting when it goes over a threshold.
|
||||
//! 4. It does not provide a `get_mut` method, so the ref counted object is pinned.
|
||||
//!
|
||||
//! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
|
||||
|
||||
use crate::{
|
||||
bindings,
|
||||
error::Result,
|
||||
types::{ForeignOwnable, Opaque},
|
||||
};
|
||||
use alloc::boxed::Box;
|
||||
use core::{
|
||||
marker::{PhantomData, Unsize},
|
||||
mem::{ManuallyDrop, MaybeUninit},
|
||||
ops::{Deref, DerefMut},
|
||||
pin::Pin,
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
||||
/// A reference-counted pointer to an instance of `T`.
|
||||
///
|
||||
/// The reference count is incremented when new instances of [`Arc`] are created, and decremented
|
||||
/// when they are dropped. When the count reaches zero, the underlying `T` is also dropped.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// The reference count on an instance of [`Arc`] is always non-zero.
|
||||
/// The object pointed to by [`Arc`] is always pinned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use kernel::sync::Arc;
|
||||
///
|
||||
/// struct Example {
|
||||
/// a: u32,
|
||||
/// b: u32,
|
||||
/// }
|
||||
///
|
||||
/// // Create a ref-counted instance of `Example`.
|
||||
/// let obj = Arc::try_new(Example { a: 10, b: 20 })?;
|
||||
///
|
||||
/// // Get a new pointer to `obj` and increment the refcount.
|
||||
/// let cloned = obj.clone();
|
||||
///
|
||||
/// // Assert that both `obj` and `cloned` point to the same underlying object.
|
||||
/// assert!(core::ptr::eq(&*obj, &*cloned));
|
||||
///
|
||||
/// // Destroy `obj` and decrement its refcount.
|
||||
/// drop(obj);
|
||||
///
|
||||
/// // Check that the values are still accessible through `cloned`.
|
||||
/// assert_eq!(cloned.a, 10);
|
||||
/// assert_eq!(cloned.b, 20);
|
||||
///
|
||||
/// // The refcount drops to zero when `cloned` goes out of scope, and the memory is freed.
|
||||
/// ```
|
||||
///
|
||||
/// Using `Arc<T>` as the type of `self`:
|
||||
///
|
||||
/// ```
|
||||
/// use kernel::sync::Arc;
|
||||
///
|
||||
/// struct Example {
|
||||
/// a: u32,
|
||||
/// b: u32,
|
||||
/// }
|
||||
///
|
||||
/// impl Example {
|
||||
/// fn take_over(self: Arc<Self>) {
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// fn use_reference(self: &Arc<Self>) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let obj = Arc::try_new(Example { a: 10, b: 20 })?;
|
||||
/// obj.use_reference();
|
||||
/// obj.take_over();
|
||||
/// ```
|
||||
///
|
||||
/// Coercion from `Arc<Example>` to `Arc<dyn MyTrait>`:
|
||||
///
|
||||
/// ```
|
||||
/// use kernel::sync::{Arc, ArcBorrow};
|
||||
///
|
||||
/// trait MyTrait {
|
||||
/// // Trait has a function whose `self` type is `Arc<Self>`.
|
||||
/// fn example1(self: Arc<Self>) {}
|
||||
///
|
||||
/// // Trait has a function whose `self` type is `ArcBorrow<'_, Self>`.
|
||||
/// fn example2(self: ArcBorrow<'_, Self>) {}
|
||||
/// }
|
||||
///
|
||||
/// struct Example;
|
||||
/// impl MyTrait for Example {}
|
||||
///
|
||||
/// // `obj` has type `Arc<Example>`.
|
||||
/// let obj: Arc<Example> = Arc::try_new(Example)?;
|
||||
///
|
||||
/// // `coerced` has type `Arc<dyn MyTrait>`.
|
||||
/// let coerced: Arc<dyn MyTrait> = obj;
|
||||
/// ```
|
||||
pub struct Arc<T: ?Sized> {
|
||||
ptr: NonNull<ArcInner<T>>,
|
||||
_p: PhantomData<ArcInner<T>>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct ArcInner<T: ?Sized> {
|
||||
refcount: Opaque<bindings::refcount_t>,
|
||||
data: T,
|
||||
}
|
||||
|
||||
// This is to allow [`Arc`] (and variants) to be used as the type of `self`.
|
||||
impl<T: ?Sized> core::ops::Receiver for Arc<T> {}
|
||||
|
||||
// This is to allow coercion from `Arc<T>` to `Arc<U>` if `T` can be converted to the
|
||||
// dynamically-sized type (DST) `U`.
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}
|
||||
|
||||
// This is to allow `Arc<U>` to be dispatched on when `Arc<T>` can be coerced into `Arc<U>`.
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
|
||||
|
||||
// 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.
|
||||
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.
|
||||
unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
|
||||
|
||||
impl<T> Arc<T> {
|
||||
/// Constructs a new reference counted instance of `T`.
|
||||
pub fn try_new(contents: T) -> Result<Self> {
|
||||
// INVARIANT: The refcount is initialised to a non-zero value.
|
||||
let value = ArcInner {
|
||||
// SAFETY: There are no safety requirements for this FFI call.
|
||||
refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) }),
|
||||
data: contents,
|
||||
};
|
||||
|
||||
let inner = Box::try_new(value)?;
|
||||
|
||||
// SAFETY: We just created `inner` with a reference count of 1, which is owned by the new
|
||||
// `Arc` object.
|
||||
Ok(unsafe { Self::from_inner(Box::leak(inner).into()) })
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Arc<T> {
|
||||
/// Constructs a new [`Arc`] from an existing [`ArcInner`].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that `inner` points to a valid location and has a non-zero reference
|
||||
/// count, one of which will be owned by the new [`Arc`] instance.
|
||||
unsafe fn from_inner(inner: NonNull<ArcInner<T>>) -> Self {
|
||||
// INVARIANT: By the safety requirements, the invariants hold.
|
||||
Arc {
|
||||
ptr: inner,
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an [`ArcBorrow`] from the given [`Arc`].
|
||||
///
|
||||
/// This is useful when the argument of a function call is an [`ArcBorrow`] (e.g., in a method
|
||||
/// receiver), but we have an [`Arc`] instead. Getting an [`ArcBorrow`] is free when optimised.
|
||||
#[inline]
|
||||
pub fn as_arc_borrow(&self) -> ArcBorrow<'_, T> {
|
||||
// SAFETY: The constraint that the lifetime of the shared reference must outlive that of
|
||||
// the returned `ArcBorrow` ensures that the object remains alive and that no mutable
|
||||
// reference can be created.
|
||||
unsafe { ArcBorrow::new(self.ptr) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> ForeignOwnable for Arc<T> {
|
||||
type Borrowed<'a> = ArcBorrow<'a, T>;
|
||||
|
||||
fn into_foreign(self) -> *const core::ffi::c_void {
|
||||
ManuallyDrop::new(self).ptr.as_ptr() as _
|
||||
}
|
||||
|
||||
unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> ArcBorrow<'a, T> {
|
||||
// SAFETY: By the safety requirement of this function, we know that `ptr` came from
|
||||
// a previous call to `Arc::into_foreign`.
|
||||
let inner = NonNull::new(ptr as *mut ArcInner<T>).unwrap();
|
||||
|
||||
// SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive
|
||||
// for the lifetime of the returned value. Additionally, the safety requirements of
|
||||
// `ForeignOwnable::borrow_mut` ensure that no new mutable references are created.
|
||||
unsafe { ArcBorrow::new(inner) }
|
||||
}
|
||||
|
||||
unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self {
|
||||
// SAFETY: By the safety requirement of this function, we know that `ptr` came from
|
||||
// a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and
|
||||
// holds a reference count increment that is transferrable to us.
|
||||
unsafe { Self::from_inner(NonNull::new(ptr as _).unwrap()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Deref for Arc<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
|
||||
// safe to dereference it.
|
||||
unsafe { &self.ptr.as_ref().data }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Clone for Arc<T> {
|
||||
fn clone(&self) -> Self {
|
||||
// INVARIANT: C `refcount_inc` saturates the refcount, so it cannot overflow to zero.
|
||||
// SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
|
||||
// safe to increment the refcount.
|
||||
unsafe { bindings::refcount_inc(self.ptr.as_ref().refcount.get()) };
|
||||
|
||||
// SAFETY: We just incremented the refcount. This increment is now owned by the new `Arc`.
|
||||
unsafe { Self::from_inner(self.ptr) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Drop for Arc<T> {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: By the type invariant, there is necessarily a reference to the object. We cannot
|
||||
// touch `refcount` after it's decremented to a non-zero value because another thread/CPU
|
||||
// may concurrently decrement it to zero and free it. It is ok to have a raw pointer to
|
||||
// freed/invalid memory as long as it is never dereferenced.
|
||||
let refcount = unsafe { self.ptr.as_ref() }.refcount.get();
|
||||
|
||||
// INVARIANT: If the refcount reaches zero, there are no other instances of `Arc`, and
|
||||
// this instance is being dropped, so the broken invariant is not observable.
|
||||
// SAFETY: Also by the type invariant, we are allowed to decrement the refcount.
|
||||
let is_zero = unsafe { bindings::refcount_dec_and_test(refcount) };
|
||||
if is_zero {
|
||||
// The count reached zero, we must free the memory.
|
||||
//
|
||||
// SAFETY: The pointer was initialised from the result of `Box::leak`.
|
||||
unsafe { Box::from_raw(self.ptr.as_ptr()) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> From<UniqueArc<T>> for Arc<T> {
|
||||
fn from(item: UniqueArc<T>) -> Self {
|
||||
item.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> From<Pin<UniqueArc<T>>> for Arc<T> {
|
||||
fn from(item: Pin<UniqueArc<T>>) -> Self {
|
||||
// SAFETY: The type invariants of `Arc` guarantee that the data is pinned.
|
||||
unsafe { Pin::into_inner_unchecked(item).inner }
|
||||
}
|
||||
}
|
||||
|
||||
/// A borrowed reference to an [`Arc`] instance.
|
||||
///
|
||||
/// For cases when one doesn't ever need to increment the refcount on the allocation, it is simpler
|
||||
/// to use just `&T`, which we can trivially get from an `Arc<T>` instance.
|
||||
///
|
||||
/// However, when one may need to increment the refcount, it is preferable to use an `ArcBorrow<T>`
|
||||
/// over `&Arc<T>` because the latter results in a double-indirection: a pointer (shared reference)
|
||||
/// to a pointer (`Arc<T>`) to the object (`T`). An [`ArcBorrow`] eliminates this double
|
||||
/// indirection while still allowing one to increment the refcount and getting an `Arc<T>` when/if
|
||||
/// needed.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// There are no mutable references to the underlying [`Arc`], and it remains valid for the
|
||||
/// lifetime of the [`ArcBorrow`] instance.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use crate::sync::{Arc, ArcBorrow};
|
||||
///
|
||||
/// struct Example;
|
||||
///
|
||||
/// fn do_something(e: ArcBorrow<'_, Example>) -> Arc<Example> {
|
||||
/// e.into()
|
||||
/// }
|
||||
///
|
||||
/// let obj = Arc::try_new(Example)?;
|
||||
/// let cloned = do_something(obj.as_arc_borrow());
|
||||
///
|
||||
/// // Assert that both `obj` and `cloned` point to the same underlying object.
|
||||
/// assert!(core::ptr::eq(&*obj, &*cloned));
|
||||
/// ```
|
||||
///
|
||||
/// Using `ArcBorrow<T>` as the type of `self`:
|
||||
///
|
||||
/// ```
|
||||
/// use crate::sync::{Arc, ArcBorrow};
|
||||
///
|
||||
/// struct Example {
|
||||
/// a: u32,
|
||||
/// b: u32,
|
||||
/// }
|
||||
///
|
||||
/// impl Example {
|
||||
/// fn use_reference(self: ArcBorrow<'_, Self>) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let obj = Arc::try_new(Example { a: 10, b: 20 })?;
|
||||
/// obj.as_arc_borrow().use_reference();
|
||||
/// ```
|
||||
pub struct ArcBorrow<'a, T: ?Sized + 'a> {
|
||||
inner: NonNull<ArcInner<T>>,
|
||||
_p: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
// This is to allow [`ArcBorrow`] (and variants) to be used as the type of `self`.
|
||||
impl<T: ?Sized> core::ops::Receiver for ArcBorrow<'_, T> {}
|
||||
|
||||
// This is to allow `ArcBorrow<U>` to be dispatched on when `ArcBorrow<T>` can be coerced into
|
||||
// `ArcBorrow<U>`.
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
|
||||
for ArcBorrow<'_, T>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Clone for ArcBorrow<'_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Copy for ArcBorrow<'_, T> {}
|
||||
|
||||
impl<T: ?Sized> ArcBorrow<'_, T> {
|
||||
/// Creates a new [`ArcBorrow`] instance.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Callers must ensure the following for the lifetime of the returned [`ArcBorrow`] instance:
|
||||
/// 1. That `inner` remains valid;
|
||||
/// 2. That no mutable references to `inner` are created.
|
||||
unsafe fn new(inner: NonNull<ArcInner<T>>) -> Self {
|
||||
// INVARIANT: The safety requirements guarantee the invariants.
|
||||
Self {
|
||||
inner,
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> From<ArcBorrow<'_, T>> for Arc<T> {
|
||||
fn from(b: ArcBorrow<'_, T>) -> Self {
|
||||
// SAFETY: The existence of `b` guarantees that the refcount is non-zero. `ManuallyDrop`
|
||||
// guarantees that `drop` isn't called, so it's ok that the temporary `Arc` doesn't own the
|
||||
// increment.
|
||||
ManuallyDrop::new(unsafe { Arc::from_inner(b.inner) })
|
||||
.deref()
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Deref for ArcBorrow<'_, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// SAFETY: By the type invariant, the underlying object is still alive with no mutable
|
||||
// references to it, so it is safe to create a shared reference.
|
||||
unsafe { &self.inner.as_ref().data }
|
||||
}
|
||||
}
|
||||
|
||||
/// A refcounted object that is known to have a refcount of 1.
|
||||
///
|
||||
/// It is mutable and can be converted to an [`Arc`] so that it can be shared.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// `inner` always has a reference count of 1.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// In the following example, we make changes to the inner object before turning it into an
|
||||
/// `Arc<Test>` object (after which point, it cannot be mutated directly). Note that `x.into()`
|
||||
/// cannot fail.
|
||||
///
|
||||
/// ```
|
||||
/// use kernel::sync::{Arc, UniqueArc};
|
||||
///
|
||||
/// struct Example {
|
||||
/// a: u32,
|
||||
/// b: u32,
|
||||
/// }
|
||||
///
|
||||
/// fn test() -> Result<Arc<Example>> {
|
||||
/// let mut x = UniqueArc::try_new(Example { a: 10, b: 20 })?;
|
||||
/// x.a += 1;
|
||||
/// x.b += 1;
|
||||
/// Ok(x.into())
|
||||
/// }
|
||||
///
|
||||
/// # test().unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// In the following example we first allocate memory for a ref-counted `Example` but we don't
|
||||
/// initialise it on allocation. We do initialise it later with a call to [`UniqueArc::write`],
|
||||
/// followed by a conversion to `Arc<Example>`. This is particularly useful when allocation happens
|
||||
/// in one context (e.g., sleepable) and initialisation in another (e.g., atomic):
|
||||
///
|
||||
/// ```
|
||||
/// use kernel::sync::{Arc, UniqueArc};
|
||||
///
|
||||
/// struct Example {
|
||||
/// a: u32,
|
||||
/// b: u32,
|
||||
/// }
|
||||
///
|
||||
/// fn test() -> Result<Arc<Example>> {
|
||||
/// let x = UniqueArc::try_new_uninit()?;
|
||||
/// Ok(x.write(Example { a: 10, b: 20 }).into())
|
||||
/// }
|
||||
///
|
||||
/// # test().unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// In the last example below, the caller gets a pinned instance of `Example` while converting to
|
||||
/// `Arc<Example>`; this is useful in scenarios where one needs a pinned reference during
|
||||
/// initialisation, for example, when initialising fields that are wrapped in locks.
|
||||
///
|
||||
/// ```
|
||||
/// use kernel::sync::{Arc, UniqueArc};
|
||||
///
|
||||
/// struct Example {
|
||||
/// a: u32,
|
||||
/// b: u32,
|
||||
/// }
|
||||
///
|
||||
/// fn test() -> Result<Arc<Example>> {
|
||||
/// let mut pinned = Pin::from(UniqueArc::try_new(Example { a: 10, b: 20 })?);
|
||||
/// // We can modify `pinned` because it is `Unpin`.
|
||||
/// pinned.as_mut().a += 1;
|
||||
/// Ok(pinned.into())
|
||||
/// }
|
||||
///
|
||||
/// # test().unwrap();
|
||||
/// ```
|
||||
pub struct UniqueArc<T: ?Sized> {
|
||||
inner: Arc<T>,
|
||||
}
|
||||
|
||||
impl<T> UniqueArc<T> {
|
||||
/// Tries to allocate a new [`UniqueArc`] instance.
|
||||
pub fn try_new(value: T) -> Result<Self> {
|
||||
Ok(Self {
|
||||
// INVARIANT: The newly-created object has a ref-count of 1.
|
||||
inner: Arc::try_new(value)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Tries to allocate a new [`UniqueArc`] instance whose contents are not initialised yet.
|
||||
pub fn try_new_uninit() -> Result<UniqueArc<MaybeUninit<T>>> {
|
||||
Ok(UniqueArc::<MaybeUninit<T>> {
|
||||
// INVARIANT: The newly-created object has a ref-count of 1.
|
||||
inner: Arc::try_new(MaybeUninit::uninit())?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UniqueArc<MaybeUninit<T>> {
|
||||
/// Converts a `UniqueArc<MaybeUninit<T>>` into a `UniqueArc<T>` by writing a value into it.
|
||||
pub fn write(mut self, value: T) -> UniqueArc<T> {
|
||||
self.deref_mut().write(value);
|
||||
let inner = ManuallyDrop::new(self).inner.ptr;
|
||||
UniqueArc {
|
||||
// SAFETY: The new `Arc` is taking over `ptr` from `self.inner` (which won't be
|
||||
// dropped). The types are compatible because `MaybeUninit<T>` is compatible with `T`.
|
||||
inner: unsafe { Arc::from_inner(inner.cast()) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> From<UniqueArc<T>> for Pin<UniqueArc<T>> {
|
||||
fn from(obj: UniqueArc<T>) -> Self {
|
||||
// SAFETY: It is not possible to move/replace `T` inside a `Pin<UniqueArc<T>>` (unless `T`
|
||||
// is `Unpin`), so it is ok to convert it to `Pin<UniqueArc<T>>`.
|
||||
unsafe { Pin::new_unchecked(obj) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Deref for UniqueArc<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.inner.deref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> DerefMut for UniqueArc<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
// SAFETY: By the `Arc` type invariant, there is necessarily a reference to the object, so
|
||||
// it is safe to dereference it. Additionally, we know there is only one reference when
|
||||
// it's inside a `UniqueArc`, so it is safe to get a mutable reference.
|
||||
unsafe { &mut self.inner.ptr.as_mut().data }
|
||||
}
|
||||
}
|
@ -2,7 +2,220 @@
|
||||
|
||||
//! Kernel types.
|
||||
|
||||
use core::{cell::UnsafeCell, mem::MaybeUninit};
|
||||
use alloc::boxed::Box;
|
||||
use core::{
|
||||
cell::UnsafeCell,
|
||||
mem::MaybeUninit,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
/// Used to transfer ownership to and from foreign (non-Rust) languages.
|
||||
///
|
||||
/// Ownership is transferred from Rust to a foreign language by calling [`Self::into_foreign`] and
|
||||
/// later may be transferred back to Rust by calling [`Self::from_foreign`].
|
||||
///
|
||||
/// This trait is meant to be used in cases when Rust objects are stored in C objects and
|
||||
/// eventually "freed" back to Rust.
|
||||
pub trait ForeignOwnable: Sized {
|
||||
/// Type of values borrowed between calls to [`ForeignOwnable::into_foreign`] and
|
||||
/// [`ForeignOwnable::from_foreign`].
|
||||
type Borrowed<'a>;
|
||||
|
||||
/// Converts a Rust-owned object to a foreign-owned one.
|
||||
///
|
||||
/// The foreign representation is a pointer to void.
|
||||
fn into_foreign(self) -> *const core::ffi::c_void;
|
||||
|
||||
/// Borrows a foreign-owned object.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
|
||||
/// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
|
||||
/// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow_mut`]
|
||||
/// for this object must have been dropped.
|
||||
unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a>;
|
||||
|
||||
/// Mutably borrows a foreign-owned object.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
|
||||
/// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
|
||||
/// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and
|
||||
/// [`ForeignOwnable::borrow_mut`] for this object must have been dropped.
|
||||
unsafe fn borrow_mut(ptr: *const core::ffi::c_void) -> ScopeGuard<Self, fn(Self)> {
|
||||
// SAFETY: The safety requirements ensure that `ptr` came from a previous call to
|
||||
// `into_foreign`.
|
||||
ScopeGuard::new_with_data(unsafe { Self::from_foreign(ptr) }, |d| {
|
||||
d.into_foreign();
|
||||
})
|
||||
}
|
||||
|
||||
/// Converts a foreign-owned object back to a Rust-owned one.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
|
||||
/// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
|
||||
/// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and
|
||||
/// [`ForeignOwnable::borrow_mut`] for this object must have been dropped.
|
||||
unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self;
|
||||
}
|
||||
|
||||
impl<T: 'static> ForeignOwnable for Box<T> {
|
||||
type Borrowed<'a> = &'a T;
|
||||
|
||||
fn into_foreign(self) -> *const core::ffi::c_void {
|
||||
Box::into_raw(self) as _
|
||||
}
|
||||
|
||||
unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> &'a T {
|
||||
// SAFETY: The safety requirements for this function ensure that the object is still alive,
|
||||
// so it is safe to dereference the raw pointer.
|
||||
// The safety requirements of `from_foreign` also ensure that the object remains alive for
|
||||
// the lifetime of the returned value.
|
||||
unsafe { &*ptr.cast() }
|
||||
}
|
||||
|
||||
unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self {
|
||||
// SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
|
||||
// call to `Self::into_foreign`.
|
||||
unsafe { Box::from_raw(ptr as _) }
|
||||
}
|
||||
}
|
||||
|
||||
impl ForeignOwnable for () {
|
||||
type Borrowed<'a> = ();
|
||||
|
||||
fn into_foreign(self) -> *const core::ffi::c_void {
|
||||
core::ptr::NonNull::dangling().as_ptr()
|
||||
}
|
||||
|
||||
unsafe fn borrow<'a>(_: *const core::ffi::c_void) -> Self::Borrowed<'a> {}
|
||||
|
||||
unsafe fn from_foreign(_: *const core::ffi::c_void) -> Self {}
|
||||
}
|
||||
|
||||
/// Runs a cleanup function/closure when dropped.
|
||||
///
|
||||
/// The [`ScopeGuard::dismiss`] function prevents the cleanup function from running.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// In the example below, we have multiple exit paths and we want to log regardless of which one is
|
||||
/// taken:
|
||||
/// ```
|
||||
/// # use kernel::ScopeGuard;
|
||||
/// fn example1(arg: bool) {
|
||||
/// let _log = ScopeGuard::new(|| pr_info!("example1 completed\n"));
|
||||
///
|
||||
/// if arg {
|
||||
/// return;
|
||||
/// }
|
||||
///
|
||||
/// pr_info!("Do something...\n");
|
||||
/// }
|
||||
///
|
||||
/// # example1(false);
|
||||
/// # example1(true);
|
||||
/// ```
|
||||
///
|
||||
/// In the example below, we want to log the same message on all early exits but a different one on
|
||||
/// the main exit path:
|
||||
/// ```
|
||||
/// # use kernel::ScopeGuard;
|
||||
/// fn example2(arg: bool) {
|
||||
/// let log = ScopeGuard::new(|| pr_info!("example2 returned early\n"));
|
||||
///
|
||||
/// if arg {
|
||||
/// return;
|
||||
/// }
|
||||
///
|
||||
/// // (Other early returns...)
|
||||
///
|
||||
/// log.dismiss();
|
||||
/// pr_info!("example2 no early return\n");
|
||||
/// }
|
||||
///
|
||||
/// # example2(false);
|
||||
/// # example2(true);
|
||||
/// ```
|
||||
///
|
||||
/// In the example below, we need a mutable object (the vector) to be accessible within the log
|
||||
/// function, so we wrap it in the [`ScopeGuard`]:
|
||||
/// ```
|
||||
/// # use kernel::ScopeGuard;
|
||||
/// fn example3(arg: bool) -> Result {
|
||||
/// let mut vec =
|
||||
/// ScopeGuard::new_with_data(Vec::new(), |v| pr_info!("vec had {} elements\n", v.len()));
|
||||
///
|
||||
/// vec.try_push(10u8)?;
|
||||
/// if arg {
|
||||
/// return Ok(());
|
||||
/// }
|
||||
/// vec.try_push(20u8)?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
///
|
||||
/// # assert_eq!(example3(false), Ok(()));
|
||||
/// # assert_eq!(example3(true), Ok(()));
|
||||
/// ```
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// The value stored in the struct is nearly always `Some(_)`, except between
|
||||
/// [`ScopeGuard::dismiss`] and [`ScopeGuard::drop`]: in this case, it will be `None` as the value
|
||||
/// will have been returned to the caller. Since [`ScopeGuard::dismiss`] consumes the guard,
|
||||
/// callers won't be able to use it anymore.
|
||||
pub struct ScopeGuard<T, F: FnOnce(T)>(Option<(T, F)>);
|
||||
|
||||
impl<T, F: FnOnce(T)> ScopeGuard<T, F> {
|
||||
/// Creates a new guarded object wrapping the given data and with the given cleanup function.
|
||||
pub fn new_with_data(data: T, cleanup_func: F) -> Self {
|
||||
// INVARIANT: The struct is being initialised with `Some(_)`.
|
||||
Self(Some((data, cleanup_func)))
|
||||
}
|
||||
|
||||
/// Prevents the cleanup function from running and returns the guarded data.
|
||||
pub fn dismiss(mut self) -> T {
|
||||
// INVARIANT: This is the exception case in the invariant; it is not visible to callers
|
||||
// because this function consumes `self`.
|
||||
self.0.take().unwrap().0
|
||||
}
|
||||
}
|
||||
|
||||
impl ScopeGuard<(), fn(())> {
|
||||
/// Creates a new guarded object with the given cleanup function.
|
||||
pub fn new(cleanup: impl FnOnce()) -> ScopeGuard<(), impl FnOnce(())> {
|
||||
ScopeGuard::new_with_data((), move |_| cleanup())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, F: FnOnce(T)> Deref for ScopeGuard<T, F> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
// The type invariants guarantee that `unwrap` will succeed.
|
||||
&self.0.as_ref().unwrap().0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, F: FnOnce(T)> DerefMut for ScopeGuard<T, F> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
// The type invariants guarantee that `unwrap` will succeed.
|
||||
&mut self.0.as_mut().unwrap().0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, F: FnOnce(T)> Drop for ScopeGuard<T, F> {
|
||||
fn drop(&mut self) {
|
||||
// Run the cleanup function if one is still present.
|
||||
if let Some((data, cleanup)) = self.0.take() {
|
||||
cleanup(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores an opaque value.
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user