mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Merge tag 'alloc-next-v6.16-2025-05-13' of https://github.com/Rust-for-Linux/linux into rust-next
Pull alloc updates from Danilo Krummrich:
"Box:
- Support for type coercion, e.g. 'Box<T>' to 'Box<dyn U>' if T
implements U
Vec:
- Implement new methods (prerequisites for nova-core and binder)
- Vec::truncate()
- Vec::resize()
- Vec::clear()
- Vec::pop()
- Vec::push_within_capacity()
- New error type: PushError
- Vec::drain_all()
- Vec::retain()
- Vec::remove()
- New error type: RemoveError
- Vec::insert_within_capacity
- New error type: InsertError
- Simplify Vec::push() using Vec::spare_capacity_mut()
- Split Vec::set_len() into Vec::inc_len() and Vec::dec_len()
- Add type invariant Vec::len() <= Vec::capacity
- Simplify Vec::truncate() using Vec::dec_len()"
* tag 'alloc-next-v6.16-2025-05-13' of https://github.com/Rust-for-Linux/linux:
rust: alloc: add Vec::insert_within_capacity
rust: alloc: add Vec::remove
rust: alloc: add Vec::retain
rust: alloc: add Vec::drain_all
rust: alloc: add Vec::push_within_capacity
rust: alloc: add Vec::pop
rust: alloc: add Vec::clear
rust: alloc: replace `Vec::set_len` with `inc_len`
rust: alloc: refactor `Vec::truncate` using `dec_len`
rust: alloc: add `Vec::dec_len`
rust: alloc: add Vec::len() <= Vec::capacity invariant
rust: alloc: allow coercion from `Box<T>` to `Box<dyn U>` if T implements U
rust: alloc: use `spare_capacity_mut` to reduce unsafe
rust: alloc: add Vec::resize method
rust: alloc: add Vec::truncate method
rust: alloc: add missing invariant in Vec::set_len()
This commit is contained in:
@@ -57,12 +57,50 @@ use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption};
|
||||
/// assert!(KVBox::<Huge>::new_uninit(GFP_KERNEL).is_ok());
|
||||
/// ```
|
||||
///
|
||||
/// [`Box`]es can also be used to store trait objects by coercing their type:
|
||||
///
|
||||
/// ```
|
||||
/// trait FooTrait {}
|
||||
///
|
||||
/// struct FooStruct;
|
||||
/// impl FooTrait for FooStruct {}
|
||||
///
|
||||
/// let _ = KBox::new(FooStruct, GFP_KERNEL)? as KBox<dyn FooTrait>;
|
||||
/// # Ok::<(), Error>(())
|
||||
/// ```
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// `self.0` is always properly aligned and either points to memory allocated with `A` or, for
|
||||
/// zero-sized types, is a dangling, well aligned pointer.
|
||||
#[repr(transparent)]
|
||||
pub struct Box<T: ?Sized, A: Allocator>(NonNull<T>, PhantomData<A>);
|
||||
#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]
|
||||
pub struct Box<#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, pointee)] T: ?Sized, A: Allocator>(
|
||||
NonNull<T>,
|
||||
PhantomData<A>,
|
||||
);
|
||||
|
||||
// This is to allow coercion from `Box<T, A>` to `Box<U, A>` if `T` can be converted to the
|
||||
// dynamically-sized type (DST) `U`.
|
||||
#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
|
||||
impl<T, U, A> core::ops::CoerceUnsized<Box<U, A>> for Box<T, A>
|
||||
where
|
||||
T: ?Sized + core::marker::Unsize<U>,
|
||||
U: ?Sized,
|
||||
A: Allocator,
|
||||
{
|
||||
}
|
||||
|
||||
// This is to allow `Box<U, A>` to be dispatched on when `Box<T, A>` can be coerced into `Box<U,
|
||||
// A>`.
|
||||
#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
|
||||
impl<T, U, A> core::ops::DispatchFromDyn<Box<U, A>> for Box<T, A>
|
||||
where
|
||||
T: ?Sized + core::marker::Unsize<U>,
|
||||
U: ?Sized,
|
||||
A: Allocator,
|
||||
{
|
||||
}
|
||||
|
||||
/// Type alias for [`Box`] with a [`Kmalloc`] allocator.
|
||||
///
|
||||
|
||||
@@ -24,6 +24,9 @@ use core::{
|
||||
slice::SliceIndex,
|
||||
};
|
||||
|
||||
mod errors;
|
||||
pub use self::errors::{InsertError, PushError, RemoveError};
|
||||
|
||||
/// Create a [`KVec`] containing the arguments.
|
||||
///
|
||||
/// New memory is allocated with `GFP_KERNEL`.
|
||||
@@ -93,6 +96,8 @@ macro_rules! kvec {
|
||||
/// without re-allocation. For ZSTs `self.layout`'s capacity is zero. However, it is legal for the
|
||||
/// backing buffer to be larger than `layout`.
|
||||
///
|
||||
/// - `self.len()` is always less than or equal to `self.capacity()`.
|
||||
///
|
||||
/// - The `Allocator` type `A` of the vector is the exact same `Allocator` type the backing buffer
|
||||
/// was allocated with (and must be freed with).
|
||||
pub struct Vec<T, A: Allocator> {
|
||||
@@ -186,17 +191,38 @@ where
|
||||
self.len
|
||||
}
|
||||
|
||||
/// Forcefully sets `self.len` to `new_len`.
|
||||
/// Increments `self.len` by `additional`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `new_len` must be less than or equal to [`Self::capacity`].
|
||||
/// - If `new_len` is greater than `self.len`, all elements within the interval
|
||||
/// [`self.len`,`new_len`) must be initialized.
|
||||
/// - `additional` must be less than or equal to `self.capacity - self.len`.
|
||||
/// - All elements within the interval [`self.len`,`self.len + additional`) must be initialized.
|
||||
#[inline]
|
||||
pub unsafe fn set_len(&mut self, new_len: usize) {
|
||||
debug_assert!(new_len <= self.capacity());
|
||||
self.len = new_len;
|
||||
pub unsafe fn inc_len(&mut self, additional: usize) {
|
||||
// Guaranteed by the type invariant to never underflow.
|
||||
debug_assert!(additional <= self.capacity() - self.len());
|
||||
// INVARIANT: By the safety requirements of this method this represents the exact number of
|
||||
// elements stored within `self`.
|
||||
self.len += additional;
|
||||
}
|
||||
|
||||
/// Decreases `self.len` by `count`.
|
||||
///
|
||||
/// Returns a mutable slice to the elements forgotten by the vector. It is the caller's
|
||||
/// responsibility to drop these elements if necessary.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `count` must be less than or equal to `self.len`.
|
||||
unsafe fn dec_len(&mut self, count: usize) -> &mut [T] {
|
||||
debug_assert!(count <= self.len());
|
||||
// INVARIANT: We relinquish ownership of the elements within the range `[self.len - count,
|
||||
// self.len)`, hence the updated value of `set.len` represents the exact number of elements
|
||||
// stored within `self`.
|
||||
self.len -= count;
|
||||
// SAFETY: The memory after `self.len()` is guaranteed to contain `count` initialized
|
||||
// elements of type `T`.
|
||||
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr().add(self.len), count) }
|
||||
}
|
||||
|
||||
/// Returns a slice of the entire vector.
|
||||
@@ -262,8 +288,8 @@ where
|
||||
/// Returns a slice of `MaybeUninit<T>` for the remaining spare capacity of the vector.
|
||||
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
|
||||
// SAFETY:
|
||||
// - `self.len` is smaller than `self.capacity` and hence, the resulting pointer is
|
||||
// guaranteed to be part of the same allocated object.
|
||||
// - `self.len` is smaller than `self.capacity` by the type invariant and hence, the
|
||||
// resulting pointer is guaranteed to be part of the same allocated object.
|
||||
// - `self.len` can not overflow `isize`.
|
||||
let ptr = unsafe { self.as_mut_ptr().add(self.len) } as *mut MaybeUninit<T>;
|
||||
|
||||
@@ -287,24 +313,170 @@ where
|
||||
/// ```
|
||||
pub fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError> {
|
||||
self.reserve(1, flags)?;
|
||||
// SAFETY: The call to `reserve` was successful, so the capacity is at least one greater
|
||||
// than the length.
|
||||
unsafe { self.push_within_capacity_unchecked(v) };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// SAFETY:
|
||||
// - `self.len` is smaller than `self.capacity` and hence, the resulting pointer is
|
||||
// guaranteed to be part of the same allocated object.
|
||||
// - `self.len` can not overflow `isize`.
|
||||
let ptr = unsafe { self.as_mut_ptr().add(self.len) };
|
||||
/// Appends an element to the back of the [`Vec`] instance without reallocating.
|
||||
///
|
||||
/// Fails if the vector does not have capacity for the new element.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = KVec::with_capacity(10, GFP_KERNEL)?;
|
||||
/// for i in 0..10 {
|
||||
/// v.push_within_capacity(i)?;
|
||||
/// }
|
||||
///
|
||||
/// assert!(v.push_within_capacity(10).is_err());
|
||||
/// # Ok::<(), Error>(())
|
||||
/// ```
|
||||
pub fn push_within_capacity(&mut self, v: T) -> Result<(), PushError<T>> {
|
||||
if self.len() < self.capacity() {
|
||||
// SAFETY: The length is less than the capacity.
|
||||
unsafe { self.push_within_capacity_unchecked(v) };
|
||||
Ok(())
|
||||
} else {
|
||||
Err(PushError(v))
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY:
|
||||
// - `ptr` is properly aligned and valid for writes.
|
||||
unsafe { core::ptr::write(ptr, v) };
|
||||
/// Appends an element to the back of the [`Vec`] instance without reallocating.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The length must be less than the capacity.
|
||||
unsafe fn push_within_capacity_unchecked(&mut self, v: T) {
|
||||
let spare = self.spare_capacity_mut();
|
||||
|
||||
// SAFETY: By the safety requirements, `spare` is non-empty.
|
||||
unsafe { spare.get_unchecked_mut(0) }.write(v);
|
||||
|
||||
// SAFETY: We just initialised the first spare entry, so it is safe to increase the length
|
||||
// by 1. We also know that the new length is <= capacity because of the previous call to
|
||||
// `reserve` above.
|
||||
unsafe { self.set_len(self.len() + 1) };
|
||||
// by 1. We also know that the new length is <= capacity because the caller guarantees that
|
||||
// the length is less than the capacity at the beginning of this function.
|
||||
unsafe { self.inc_len(1) };
|
||||
}
|
||||
|
||||
/// Inserts an element at the given index in the [`Vec`] instance.
|
||||
///
|
||||
/// Fails if the vector does not have capacity for the new element. Panics if the index is out
|
||||
/// of bounds.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use kernel::alloc::kvec::InsertError;
|
||||
///
|
||||
/// let mut v = KVec::with_capacity(5, GFP_KERNEL)?;
|
||||
/// for i in 0..5 {
|
||||
/// v.insert_within_capacity(0, i)?;
|
||||
/// }
|
||||
///
|
||||
/// assert!(matches!(v.insert_within_capacity(0, 5), Err(InsertError::OutOfCapacity(_))));
|
||||
/// assert!(matches!(v.insert_within_capacity(1000, 5), Err(InsertError::IndexOutOfBounds(_))));
|
||||
/// assert_eq!(v, [4, 3, 2, 1, 0]);
|
||||
/// # Ok::<(), Error>(())
|
||||
/// ```
|
||||
pub fn insert_within_capacity(
|
||||
&mut self,
|
||||
index: usize,
|
||||
element: T,
|
||||
) -> Result<(), InsertError<T>> {
|
||||
let len = self.len();
|
||||
if index > len {
|
||||
return Err(InsertError::IndexOutOfBounds(element));
|
||||
}
|
||||
|
||||
if len >= self.capacity() {
|
||||
return Err(InsertError::OutOfCapacity(element));
|
||||
}
|
||||
|
||||
// SAFETY: This is in bounds since `index <= len < capacity`.
|
||||
let p = unsafe { self.as_mut_ptr().add(index) };
|
||||
// INVARIANT: This breaks the Vec invariants by making `index` contain an invalid element,
|
||||
// but we restore the invariants below.
|
||||
// SAFETY: Both the src and dst ranges end no later than one element after the length.
|
||||
// Since the length is less than the capacity, both ranges are in bounds of the allocation.
|
||||
unsafe { ptr::copy(p, p.add(1), len - index) };
|
||||
// INVARIANT: This restores the Vec invariants.
|
||||
// SAFETY: The pointer is in-bounds of the allocation.
|
||||
unsafe { ptr::write(p, element) };
|
||||
// SAFETY: Index `len` contains a valid element due to the above copy and write.
|
||||
unsafe { self.inc_len(1) };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes the last element from a vector and returns it, or `None` if it is empty.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = KVec::new();
|
||||
/// v.push(1, GFP_KERNEL)?;
|
||||
/// v.push(2, GFP_KERNEL)?;
|
||||
/// assert_eq!(&v, &[1, 2]);
|
||||
///
|
||||
/// assert_eq!(v.pop(), Some(2));
|
||||
/// assert_eq!(v.pop(), Some(1));
|
||||
/// assert_eq!(v.pop(), None);
|
||||
/// # Ok::<(), Error>(())
|
||||
/// ```
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
if self.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let removed: *mut T = {
|
||||
// SAFETY: We just checked that the length is at least one.
|
||||
let slice = unsafe { self.dec_len(1) };
|
||||
// SAFETY: The argument to `dec_len` was 1 so this returns a slice of length 1.
|
||||
unsafe { slice.get_unchecked_mut(0) }
|
||||
};
|
||||
|
||||
// SAFETY: The guarantees of `dec_len` allow us to take ownership of this value.
|
||||
Some(unsafe { removed.read() })
|
||||
}
|
||||
|
||||
/// Removes the element at the given index.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = kernel::kvec![1, 2, 3]?;
|
||||
/// assert_eq!(v.remove(1)?, 2);
|
||||
/// assert_eq!(v, [1, 3]);
|
||||
/// # Ok::<(), Error>(())
|
||||
/// ```
|
||||
pub fn remove(&mut self, i: usize) -> Result<T, RemoveError> {
|
||||
let value = {
|
||||
let value_ref = self.get(i).ok_or(RemoveError)?;
|
||||
// INVARIANT: This breaks the invariants by invalidating the value at index `i`, but we
|
||||
// restore the invariants below.
|
||||
// SAFETY: The value at index `i` is valid, because otherwise we would have already
|
||||
// failed with `RemoveError`.
|
||||
unsafe { ptr::read(value_ref) }
|
||||
};
|
||||
|
||||
// SAFETY: We checked that `i` is in-bounds.
|
||||
let p = unsafe { self.as_mut_ptr().add(i) };
|
||||
|
||||
// INVARIANT: After this call, the invalid value is at the last slot, so the Vec invariants
|
||||
// are restored after the below call to `dec_len(1)`.
|
||||
// SAFETY: `p.add(1).add(self.len - i - 1)` is `i+1+len-i-1 == len` elements after the
|
||||
// beginning of the vector, so this is in-bounds of the vector's allocation.
|
||||
unsafe { ptr::copy(p.add(1), p, self.len - i - 1) };
|
||||
|
||||
// SAFETY: Since the check at the beginning of this call did not fail with `RemoveError`,
|
||||
// the length is at least one.
|
||||
unsafe { self.dec_len(1) };
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
/// Creates a new [`Vec`] instance with at least the given capacity.
|
||||
///
|
||||
/// # Examples
|
||||
@@ -398,6 +570,26 @@ where
|
||||
(ptr, len, capacity)
|
||||
}
|
||||
|
||||
/// Clears the vector, removing all values.
|
||||
///
|
||||
/// Note that this method has no effect on the allocated capacity
|
||||
/// of the vector.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = kernel::kvec![1, 2, 3]?;
|
||||
///
|
||||
/// v.clear();
|
||||
///
|
||||
/// assert!(v.is_empty());
|
||||
/// # Ok::<(), Error>(())
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn clear(&mut self) {
|
||||
self.truncate(0);
|
||||
}
|
||||
|
||||
/// Ensures that the capacity exceeds the length by at least `additional` elements.
|
||||
///
|
||||
/// # Examples
|
||||
@@ -455,6 +647,80 @@ where
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Shortens the vector, setting the length to `len` and drops the removed values.
|
||||
/// If `len` is greater than or equal to the current length, this does nothing.
|
||||
///
|
||||
/// This has no effect on the capacity and will not allocate.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = kernel::kvec![1, 2, 3]?;
|
||||
/// v.truncate(1);
|
||||
/// assert_eq!(v.len(), 1);
|
||||
/// assert_eq!(&v, &[1]);
|
||||
///
|
||||
/// # Ok::<(), Error>(())
|
||||
/// ```
|
||||
pub fn truncate(&mut self, len: usize) {
|
||||
if let Some(count) = self.len().checked_sub(len) {
|
||||
// SAFETY: `count` is `self.len() - len` so it is guaranteed to be less than or
|
||||
// equal to `self.len()`.
|
||||
let ptr: *mut [T] = unsafe { self.dec_len(count) };
|
||||
|
||||
// SAFETY: the contract of `dec_len` guarantees that the elements in `ptr` are
|
||||
// valid elements whose ownership has been transferred to the caller.
|
||||
unsafe { ptr::drop_in_place(ptr) };
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes ownership of all items in this vector without consuming the allocation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = kernel::kvec![0, 1, 2, 3]?;
|
||||
///
|
||||
/// for (i, j) in v.drain_all().enumerate() {
|
||||
/// assert_eq!(i, j);
|
||||
/// }
|
||||
///
|
||||
/// assert!(v.capacity() >= 4);
|
||||
/// # Ok::<(), Error>(())
|
||||
/// ```
|
||||
pub fn drain_all(&mut self) -> DrainAll<'_, T> {
|
||||
// SAFETY: This does not underflow the length.
|
||||
let elems = unsafe { self.dec_len(self.len()) };
|
||||
// INVARIANT: The first `len` elements of the spare capacity are valid values, and as we
|
||||
// just set the length to zero, we may transfer ownership to the `DrainAll` object.
|
||||
DrainAll {
|
||||
elements: elems.iter_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes all elements that don't match the provided closure.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = kernel::kvec![1, 2, 3, 4]?;
|
||||
/// v.retain(|i| *i % 2 == 0);
|
||||
/// assert_eq!(v, [2, 4]);
|
||||
/// # Ok::<(), Error>(())
|
||||
/// ```
|
||||
pub fn retain(&mut self, mut f: impl FnMut(&mut T) -> bool) {
|
||||
let mut num_kept = 0;
|
||||
let mut next_to_check = 0;
|
||||
while let Some(to_check) = self.get_mut(next_to_check) {
|
||||
if f(to_check) {
|
||||
self.swap(num_kept, next_to_check);
|
||||
num_kept += 1;
|
||||
}
|
||||
next_to_check += 1;
|
||||
}
|
||||
self.truncate(num_kept);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone, A: Allocator> Vec<T, A> {
|
||||
@@ -478,7 +744,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
|
||||
// SAFETY:
|
||||
// - `self.len() + n < self.capacity()` due to the call to reserve above,
|
||||
// - the loop and the line above initialized the next `n` elements.
|
||||
unsafe { self.set_len(self.len() + n) };
|
||||
unsafe { self.inc_len(n) };
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -509,7 +775,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
|
||||
// the length by the same number.
|
||||
// - `self.len() + other.len() <= self.capacity()` is guaranteed by the preceding `reserve`
|
||||
// call.
|
||||
unsafe { self.set_len(self.len() + other.len()) };
|
||||
unsafe { self.inc_len(other.len()) };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -521,6 +787,33 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
|
||||
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
/// Resizes the [`Vec`] so that `len` is equal to `new_len`.
|
||||
///
|
||||
/// If `new_len` is smaller than `len`, the `Vec` is [`Vec::truncate`]d.
|
||||
/// If `new_len` is larger, each new slot is filled with clones of `value`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = kernel::kvec![1, 2, 3]?;
|
||||
/// v.resize(1, 42, GFP_KERNEL)?;
|
||||
/// assert_eq!(&v, &[1]);
|
||||
///
|
||||
/// v.resize(3, 42, GFP_KERNEL)?;
|
||||
/// assert_eq!(&v, &[1, 42, 42]);
|
||||
///
|
||||
/// # Ok::<(), Error>(())
|
||||
/// ```
|
||||
pub fn resize(&mut self, new_len: usize, value: T, flags: Flags) -> Result<(), AllocError> {
|
||||
match new_len.checked_sub(self.len()) {
|
||||
Some(n) => self.extend_with(n, value, flags),
|
||||
None => {
|
||||
self.truncate(new_len);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A> Drop for Vec<T, A>
|
||||
@@ -760,12 +1053,13 @@ where
|
||||
unsafe { ptr::copy(ptr, buf.as_ptr(), len) };
|
||||
ptr = buf.as_ptr();
|
||||
|
||||
// SAFETY: `len` is guaranteed to be smaller than `self.layout.len()`.
|
||||
// SAFETY: `len` is guaranteed to be smaller than `self.layout.len()` by the type
|
||||
// invariant.
|
||||
let layout = unsafe { ArrayLayout::<T>::new_unchecked(len) };
|
||||
|
||||
// SAFETY: `buf` points to the start of the backing buffer and `len` is guaranteed to be
|
||||
// smaller than `cap`. Depending on `alloc` this operation may shrink the buffer or leaves
|
||||
// it as it is.
|
||||
// SAFETY: `buf` points to the start of the backing buffer and `len` is guaranteed by
|
||||
// the type invariant to be smaller than `cap`. Depending on `realloc` this operation
|
||||
// may shrink the buffer or leave it as it is.
|
||||
ptr = match unsafe {
|
||||
A::realloc(Some(buf.cast()), layout.into(), old_layout.into(), flags)
|
||||
} {
|
||||
@@ -914,3 +1208,87 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator that owns all items in a vector, but does not own its allocation.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// Every `&mut T` returned by the iterator references a `T` that the iterator may take ownership
|
||||
/// of.
|
||||
pub struct DrainAll<'vec, T> {
|
||||
elements: slice::IterMut<'vec, T>,
|
||||
}
|
||||
|
||||
impl<'vec, T> Iterator for DrainAll<'vec, T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
let elem: *mut T = self.elements.next()?;
|
||||
// SAFETY: By the type invariants, we may take ownership of this value.
|
||||
Some(unsafe { elem.read() })
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.elements.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'vec, T> Drop for DrainAll<'vec, T> {
|
||||
fn drop(&mut self) {
|
||||
if core::mem::needs_drop::<T>() {
|
||||
let iter = core::mem::take(&mut self.elements);
|
||||
let ptr: *mut [T] = iter.into_slice();
|
||||
// SAFETY: By the type invariants, we own these values so we may destroy them.
|
||||
unsafe { ptr::drop_in_place(ptr) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macros::kunit_tests(rust_kvec_kunit)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[test]
|
||||
fn test_kvec_retain() {
|
||||
/// Verify correctness for one specific function.
|
||||
#[expect(clippy::needless_range_loop)]
|
||||
fn verify(c: &[bool]) {
|
||||
let mut vec1: KVec<usize> = KVec::with_capacity(c.len(), GFP_KERNEL).unwrap();
|
||||
let mut vec2: KVec<usize> = KVec::with_capacity(c.len(), GFP_KERNEL).unwrap();
|
||||
|
||||
for i in 0..c.len() {
|
||||
vec1.push_within_capacity(i).unwrap();
|
||||
if c[i] {
|
||||
vec2.push_within_capacity(i).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
vec1.retain(|i| c[*i]);
|
||||
|
||||
assert_eq!(vec1, vec2);
|
||||
}
|
||||
|
||||
/// Add one to a binary integer represented as a boolean array.
|
||||
fn add(value: &mut [bool]) {
|
||||
let mut carry = true;
|
||||
for v in value {
|
||||
let new_v = carry != *v;
|
||||
carry = carry && *v;
|
||||
*v = new_v;
|
||||
}
|
||||
}
|
||||
|
||||
// This boolean array represents a function from index to boolean. We check that `retain`
|
||||
// behaves correctly for all possible boolean arrays of every possible length less than
|
||||
// ten.
|
||||
let mut func = KVec::with_capacity(10, GFP_KERNEL).unwrap();
|
||||
for len in 0..10 {
|
||||
for _ in 0u32..1u32 << len {
|
||||
verify(&func);
|
||||
add(&mut func);
|
||||
}
|
||||
func.push_within_capacity(false).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
61
rust/kernel/alloc/kvec/errors.rs
Normal file
61
rust/kernel/alloc/kvec/errors.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
//! Errors for the [`Vec`] type.
|
||||
|
||||
use core::fmt::{self, Debug, Formatter};
|
||||
use kernel::prelude::*;
|
||||
|
||||
/// Error type for [`Vec::push_within_capacity`].
|
||||
pub struct PushError<T>(pub T);
|
||||
|
||||
impl<T> Debug for PushError<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Not enough capacity")
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<PushError<T>> for Error {
|
||||
fn from(_: PushError<T>) -> Error {
|
||||
// Returning ENOMEM isn't appropriate because the system is not out of memory. The vector
|
||||
// is just full and we are refusing to resize it.
|
||||
EINVAL
|
||||
}
|
||||
}
|
||||
|
||||
/// Error type for [`Vec::remove`].
|
||||
pub struct RemoveError;
|
||||
|
||||
impl Debug for RemoveError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Index out of bounds")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RemoveError> for Error {
|
||||
fn from(_: RemoveError) -> Error {
|
||||
EINVAL
|
||||
}
|
||||
}
|
||||
|
||||
/// Error type for [`Vec::insert_within_capacity`].
|
||||
pub enum InsertError<T> {
|
||||
/// The value could not be inserted because the index is out of bounds.
|
||||
IndexOutOfBounds(T),
|
||||
/// The value could not be inserted because the vector is out of capacity.
|
||||
OutOfCapacity(T),
|
||||
}
|
||||
|
||||
impl<T> Debug for InsertError<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
InsertError::IndexOutOfBounds(_) => write!(f, "Index out of bounds"),
|
||||
InsertError::OutOfCapacity(_) => write!(f, "Not enough capacity"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<InsertError<T>> for Error {
|
||||
fn from(_: InsertError<T>) -> Error {
|
||||
EINVAL
|
||||
}
|
||||
}
|
||||
@@ -886,7 +886,7 @@ impl CString {
|
||||
|
||||
// SAFETY: The number of bytes that can be written to `f` is bounded by `size`, which is
|
||||
// `buf`'s capacity. The contents of the buffer have been initialised by writes to `f`.
|
||||
unsafe { buf.set_len(f.bytes_written()) };
|
||||
unsafe { buf.inc_len(f.bytes_written()) };
|
||||
|
||||
// Check that there are no `NUL` bytes before the end.
|
||||
// SAFETY: The buffer is valid for read because `f.bytes_written()` is bounded by `size`
|
||||
|
||||
@@ -288,7 +288,7 @@ impl UserSliceReader {
|
||||
|
||||
// SAFETY: Since the call to `read_raw` was successful, so the next `len` bytes of the
|
||||
// vector have been initialized.
|
||||
unsafe { buf.set_len(buf.len() + len) };
|
||||
unsafe { buf.inc_len(len) };
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user