summaryrefslogtreecommitdiff
path: root/rust/kernel/box_ext.rs
blob: 0bd3808e1d8924da0ec8690451532d3074c70fd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
use alloc::alloc::AllocError;
use alloc::boxed::Box;
use core::mem::MaybeUninit;

use crate::bindings;

pub trait BoxExt<T: ?Sized> {
    fn try_new_atomic(x: T) -> Result<Self, AllocError>
    where
        Self: Sized;
}

#[cfg(not(test))]
#[cfg(not(testlib))]
impl<T> BoxExt<T> for Box<T> {
    fn try_new_atomic(x: T) -> Result<Box<T>, AllocError> {
        let layout = core::alloc::Layout::new::<core::mem::MaybeUninit<T>>();
        let ptr = crate::allocator::ALLOCATOR
            .allocate_with_flags(layout, bindings::GFP_ATOMIC)?
            .cast();
        let mut boxed: Box<MaybeUninit<T>> =
            unsafe { Box::from_raw_in(ptr.as_ptr(), alloc::alloc::Global) };

        unsafe {
            boxed.as_mut_ptr().write(x);
            Ok(boxed.assume_init())
        }
    }
}