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 >