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. > +#[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), } > +// 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. Alice