Skip to content

Commit b39cf2c

Browse files
authored
Merge pull request #45 from wedsonaf/try_alloc
Add try_alloc and try_alloc_pinned to kernel module.
2 parents 4510d5a + fbfa60c commit b39cf2c

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

rust/kernel/src/lib.rs

+35
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ compile_error!("Missing kernel configuration for conditional compilation");
1212

1313
extern crate alloc;
1414

15+
use alloc::boxed::Box;
16+
use core::alloc::Layout;
17+
use core::mem::MaybeUninit;
1518
use core::panic::PanicInfo;
19+
use core::pin::Pin;
20+
use core::ptr::NonNull;
1621

1722
mod allocator;
1823
pub mod bindings;
@@ -56,3 +61,33 @@ fn panic(_info: &PanicInfo) -> ! {
5661

5762
#[global_allocator]
5863
static ALLOCATOR: allocator::KernelAllocator = allocator::KernelAllocator;
64+
65+
/// Attempts to allocate memory for `value` using the global allocator. On success, `value` is
66+
/// moved into it and returned to the caller wrapped in a `Box`.
67+
pub fn try_alloc<T>(value: T) -> KernelResult<Box<T>> {
68+
let layout = Layout::new::<MaybeUninit<T>>();
69+
let ptr: NonNull<MaybeUninit<T>> = if layout.size() == 0 {
70+
NonNull::dangling()
71+
// SAFETY: We checked that the layout size is nonzero.
72+
} else if let Some(nn) = NonNull::new(unsafe { alloc::alloc::alloc(layout) }) {
73+
nn.cast()
74+
} else {
75+
return Err(Error::ENOMEM);
76+
};
77+
78+
unsafe {
79+
// SAFETY: `ptr` was just allocated and isn't used afterwards.
80+
let mut b = Box::from_raw(ptr.as_ptr());
81+
// SAFETY: The pointer is valid for write and is properly aligned. The dangling pointer
82+
// case is only when the size of the value is zero; writing zero bytes to it is allowed.
83+
b.as_mut_ptr().write(value);
84+
// SAFETY: The value was initialised in the call above.
85+
Ok(Box::from_raw(Box::into_raw(b) as *mut T))
86+
}
87+
}
88+
89+
/// Attempts to allocate memory for `value` using the global allocator. On success, `value` is
90+
/// moved into it and returned to the caller wrapped in a pinned `Box`.
91+
pub fn try_alloc_pinned<T>(value: T) -> KernelResult<Pin<Box<T>>> {
92+
Ok(Pin::from(try_alloc(value)?))
93+
}

0 commit comments

Comments
 (0)