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

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

 



On 14.08.24 14:36, Alice Ryhl wrote:
> On Wed, Aug 14, 2024 at 2:29 PM Danilo Krummrich <dakr@xxxxxxxxxx> 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@xxxxxxxxxx> 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.

If we are this worried about not putting the array on the stack, then we
could also do this using `init!`, but the macro still would need to
count the number of elements in the array.

@Danilo, from the other thread:

> How do we get the size here? `#![feature(generic_arg_infer)]` seems to be
> unstable.

You can use a macro to count the number of elements:

    macro_rules! count_exprs {
        () => { 0 };
        ($e:expr $(,$rest:expr)* $(,)?) => {
            1 + count_exprs!($($rest,)*)
        };
    }

And then do

    match KBox::<[_; count_exprs!($($x),+)]>::new_uninit(GFP_KERNEL) {
        Ok(b) => Ok(KVec::from(KBox::write(b, [$($x),+]))),
        Err(e) => Err(e),
    }

---
Cheers,
Benno






[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