Re: [PATCH v5 13/26] rust: alloc: implement kernel `Vec` type

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Aug 14, 2024 at 10:42:28AM +0200, Alice Ryhl wrote:
> On Mon, Aug 12, 2024 at 8:25 PM Danilo Krummrich <dakr@xxxxxxxxxx> wrote:
> >
> > `Vec` provides a contiguous growable array type (such as `Vec`) with
> > contents allocated with the kernel's allocators (e.g. `Kmalloc`,
> > `Vmalloc` or `KVmalloc`).
> >
> > In contrast to Rust's `Vec` type, the kernel `Vec` type considers the
> > kernel's GFP flags for all appropriate functions, always reports
> > allocation failures through `Result<_, AllocError>` and remains
> > independent from unstable features.
> >
> > Signed-off-by: Danilo Krummrich <dakr@xxxxxxxxxx>
> > [...]
> > +impl<T, A, const N: usize> Box<[T; N], A>
> > +where
> > +    A: Allocator,
> > +{
> > +    /// Convert a `Box<[T, N], A>` to a `Vec<T, A>`.
> > +    pub fn into_vec(b: Self) -> Vec<T, A> {
> 
> Nit: I would probably make this a From impl.

Please see my reply to patch 9 of this series.

> 
> > +#[macro_export]
> > +macro_rules! kvec {
> > +    () => (
> > +        {
> > +            $crate::alloc::KVec::new()
> > +        }
> > +    );
> > +    ($elem:expr; $n:expr) => (
> > +        {
> > +            $crate::alloc::KVec::from_elem($elem, $n, GFP_KERNEL)
> > +        }
> > +    );
> > +    ($($x:expr),+ $(,)?) => (
> > +        {
> > +            match $crate::alloc::KBox::new([$($x),+], GFP_KERNEL) {
> > +                Ok(b) => Ok($crate::alloc::KBox::into_vec(b)),
> > +                Err(e) => Err(e),
> 
> Hmm. This currently generates code that:
> 
> 1. Creates the array.
> 2. Allocates the memory.
> 3. Moves the array into the box.
> 
> Whereas the stdlib macro swaps step 1 and 2. You can do the same by
> utilizing new_uninit. A sketch:
> 
> match KBox::<[_; _]>::new_uninit(GFP_KERNEL) {
>     Ok(b) => Ok(KVec::from(KBox::write(b, [$($x),+]))),
>     Err(e) => Err(e),
> }

Generally, I'm fine changing that, but what's the reason for the suggestion? It
shouldn't make a difference, does it?

> 
> > +// SAFETY: `Vec` is `Send` if `T` is `Send` because the data referenced by `self.ptr` is unaliased.
> > +unsafe impl<T, A> Send for Vec<T, A>
> > +where
> > +    T: Send,
> > +    A: Allocator,
> > +{
> > +}
> > +
> > +// SAFETY: `Vec` is `Sync` if `T` is `Sync` because the data referenced by `self.ptr` is unaliased.
> > +unsafe impl<T, A> Sync for Vec<T, A>
> > +where
> > +    T: Send,
> > +    A: Allocator,
> 
> Same comment as Box. Ditto about "unaliased". Needs `T: Sync` instead.
> 
> > +impl<T: Clone, A: Allocator> Vec<T, A> {
> > +    /// Extend the vector by `n` clones of value.
> > +    pub fn extend_with(&mut self, n: usize, value: T, flags: Flags) -> Result<(), AllocError> {
> > +        self.reserve(n, flags)?;
> > +
> > +        let spare = self.spare_capacity_mut();
> > +
> > +        for item in spare.iter_mut().take(n - 1) {
> 
> You need to handle `n == 0` here.

Gonna fix.

> 
> Alice
> 




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux