rust: adapt alloc crate to the kernel

This customizes the subset of the Rust standard library `alloc` that
was just imported as-is, mainly by:

  - Adding SPDX license identifiers.

  - Skipping modules (e.g. `rc` and `sync`) via new `cfg`s.

  - Adding fallible (`try_*`) versions of existing infallible methods
    (i.e. returning a `Result` instead of panicking).

    Since the standard library requires stable/unstable attributes,
    these additions are annotated with:

        #[stable(feature = "kernel", since = "1.0.0")]

    Using "kernel" as the feature allows to have the additions
    clearly marked. The "1.0.0" version is just a placeholder.

    (At the moment, only one is needed, but in the future more
    fallible methods will be added).

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Matthew Bakhtiari <dev@mtbk.me>
Signed-off-by: Matthew Bakhtiari <dev@mtbk.me>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
Miguel Ojeda 2021-07-03 17:02:21 +02:00
parent 753dece88d
commit 057b8d2571
14 changed files with 100 additions and 1 deletions

33
rust/alloc/README.md Normal file
View File

@ -0,0 +1,33 @@
# `alloc`
These source files come from the Rust standard library, hosted in
the <https://github.com/rust-lang/rust> repository, licensed under
"Apache-2.0 OR MIT" and adapted for kernel use. For copyright details,
see <https://github.com/rust-lang/rust/blob/master/COPYRIGHT>.
Please note that these files should be kept as close as possible to
upstream. In general, only additions should be performed (e.g. new
methods). Eventually, changes should make it into upstream so that,
at some point, this fork can be dropped from the kernel tree.
## Rationale
On one hand, kernel folks wanted to keep `alloc` in-tree to have more
freedom in both workflow and actual features if actually needed
(e.g. receiver types if we ended up using them), which is reasonable.
On the other hand, Rust folks wanted to keep `alloc` as close as
upstream as possible and avoid as much divergence as possible, which
is also reasonable.
We agreed on a middle-ground: we would keep a subset of `alloc`
in-tree that would be as small and as close as possible to upstream.
Then, upstream can start adding the functions that we add to `alloc`
etc., until we reach a point where the kernel already knows exactly
what it needs in `alloc` and all the new methods are merged into
upstream, so that we can drop `alloc` from the kernel tree and go back
to using the upstream one.
By doing this, the kernel can go a bit faster now, and Rust can
slowly incorporate and discuss the changes as needed.

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! Memory allocation APIs //! Memory allocation APIs
#![stable(feature = "alloc_module", since = "1.28.0")] #![stable(feature = "alloc_module", since = "1.28.0")]

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! A module for working with borrowed data. //! A module for working with borrowed data.
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
@ -11,7 +13,7 @@ use core::ops::{Add, AddAssign};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::borrow::{Borrow, BorrowMut}; pub use core::borrow::{Borrow, BorrowMut};
use crate::fmt; use core::fmt;
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
use crate::string::String; use crate::string::String;

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! A pointer type for heap allocation. //! A pointer type for heap allocation.
//! //!
//! [`Box<T>`], casually referred to as a 'box', provides the simplest form of //! [`Box<T>`], casually referred to as a 'box', provides the simplest form of
@ -163,9 +165,11 @@ use crate::str::from_boxed_utf8_unchecked;
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
use crate::vec::Vec; use crate::vec::Vec;
#[cfg(not(no_thin))]
#[unstable(feature = "thin_box", issue = "92791")] #[unstable(feature = "thin_box", issue = "92791")]
pub use thin::ThinBox; pub use thin::ThinBox;
#[cfg(not(no_thin))]
mod thin; mod thin;
/// A pointer type for heap allocation. /// A pointer type for heap allocation.

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! Collection types. //! Collection types.
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! # The Rust core allocation and collections library //! # The Rust core allocation and collections library
//! //!
//! This library provides smart pointers and collections for managing //! This library provides smart pointers and collections for managing
@ -192,6 +194,7 @@ extern crate std;
extern crate test; extern crate test;
// Module with internal macros used by other modules (needs to be included before other modules). // Module with internal macros used by other modules (needs to be included before other modules).
#[cfg(not(no_macros))]
#[macro_use] #[macro_use]
mod macros; mod macros;
@ -216,11 +219,16 @@ pub mod borrow;
pub mod collections; pub mod collections;
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
pub mod ffi; pub mod ffi;
#[cfg(not(no_fmt))]
pub mod fmt; pub mod fmt;
#[cfg(not(no_rc))]
pub mod rc; pub mod rc;
pub mod slice; pub mod slice;
#[cfg(not(no_str))]
pub mod str; pub mod str;
#[cfg(not(no_string))]
pub mod string; pub mod string;
#[cfg(not(no_sync))]
#[cfg(target_has_atomic = "ptr")] #[cfg(target_has_atomic = "ptr")]
pub mod sync; pub mod sync;
#[cfg(all(not(no_global_oom_handling), target_has_atomic = "ptr"))] #[cfg(all(not(no_global_oom_handling), target_has_atomic = "ptr"))]

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
#![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")] #![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")]
use core::alloc::LayoutError; use core::alloc::LayoutError;
@ -307,6 +309,12 @@ impl<T, A: Allocator> RawVec<T, A> {
} }
} }
/// The same as `reserve_for_push`, but returns on errors instead of panicking or aborting.
#[inline(never)]
pub fn try_reserve_for_push(&mut self, len: usize) -> Result<(), TryReserveError> {
self.grow_amortized(len, 1)
}
/// Ensures that the buffer contains at least enough space to hold `len + /// Ensures that the buffer contains at least enough space to hold `len +
/// additional` elements. If it doesn't already, will reallocate the /// additional` elements. If it doesn't already, will reallocate the
/// minimum possible amount of memory necessary. Generally this will be /// minimum possible amount of memory necessary. Generally this will be
@ -421,6 +429,7 @@ impl<T, A: Allocator> RawVec<T, A> {
Ok(()) Ok(())
} }
#[allow(dead_code)]
fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> { fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> {
assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity"); assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity");

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! A dynamically-sized view into a contiguous sequence, `[T]`. //! A dynamically-sized view into a contiguous sequence, `[T]`.
//! //!
//! *[See also the slice primitive type](slice).* //! *[See also the slice primitive type](slice).*

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use crate::alloc::{Allocator, Global}; use crate::alloc::{Allocator, Global};
use core::fmt; use core::fmt;
use core::iter::{FusedIterator, TrustedLen}; use core::iter::{FusedIterator, TrustedLen};

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use crate::alloc::{Allocator, Global}; use crate::alloc::{Allocator, Global};
use core::ptr::{self}; use core::ptr::{self};
use core::slice::{self}; use core::slice::{self};

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
use super::AsVecIntoIter; use super::AsVecIntoIter;
use crate::alloc::{Allocator, Global}; use crate::alloc::{Allocator, Global};
@ -9,6 +11,7 @@ use core::iter::{
}; };
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop}; use core::mem::{self, ManuallyDrop};
#[cfg(not(no_global_oom_handling))]
use core::ops::Deref; use core::ops::Deref;
use core::ptr::{self, NonNull}; use core::ptr::{self, NonNull};
use core::slice::{self}; use core::slice::{self};
@ -123,6 +126,7 @@ impl<T, A: Allocator> IntoIter<T, A> {
} }
/// Forgets to Drop the remaining elements while still allowing the backing allocation to be freed. /// Forgets to Drop the remaining elements while still allowing the backing allocation to be freed.
#[allow(dead_code)]
pub(crate) fn forget_remaining_elements(&mut self) { pub(crate) fn forget_remaining_elements(&mut self) {
self.ptr = self.end; self.ptr = self.end;
} }

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use crate::boxed::Box; use crate::boxed::Box;
#[rustc_specialization_trait] #[rustc_specialization_trait]

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! A contiguous growable array type with heap-allocated contents, written //! A contiguous growable array type with heap-allocated contents, written
//! `Vec<T>`. //! `Vec<T>`.
//! //!
@ -1739,6 +1741,29 @@ impl<T, A: Allocator> Vec<T, A> {
} }
} }
/// Tries to append an element to the back of a collection.
///
/// # Examples
///
/// ```
/// let mut vec = vec![1, 2];
/// vec.try_push(3).unwrap();
/// assert_eq!(vec, [1, 2, 3]);
/// ```
#[inline]
#[stable(feature = "kernel", since = "1.0.0")]
pub fn try_push(&mut self, value: T) -> Result<(), TryReserveError> {
if self.len == self.buf.capacity() {
self.buf.try_reserve_for_push(self.len)?;
}
unsafe {
let end = self.as_mut_ptr().add(self.len);
ptr::write(end, value);
self.len += 1;
}
Ok(())
}
/// Removes the last element from a vector and returns it, or [`None`] if it /// Removes the last element from a vector and returns it, or [`None`] if it
/// is empty. /// is empty.
/// ///

View File

@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use crate::alloc::Allocator; use crate::alloc::Allocator;
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
use crate::borrow::Cow; use crate::borrow::Cow;