@@ -12,7 +12,12 @@ compile_error!("Missing kernel configuration for conditional compilation");
1212
1313extern crate alloc;
1414
15+ use alloc:: boxed:: Box ;
16+ use core:: alloc:: Layout ;
17+ use core:: mem:: MaybeUninit ;
1518use core:: panic:: PanicInfo ;
19+ use core:: pin:: Pin ;
20+ use core:: ptr:: NonNull ;
1621
1722mod allocator;
1823pub mod bindings;
@@ -56,3 +61,33 @@ fn panic(_info: &PanicInfo) -> ! {
5661
5762#[ global_allocator]
5863static 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