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

Alice Ryhl
2024-08-14T12:37:00Z

On Wed, Aug 14, 2024 at 2:29 PM Danilo Krummrich <dakr@kernel.org> wrote:
>
> 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@kernel.org> wrote:
> > > +#[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?

The compiler is much more likely to not put the array on the stack
before it is copied to the heap.

In the case where $x constructs new values, it also avoids
create-then-destroy on allocator failure.

Alice