@@ -9,6 +9,36 @@ use crate::bindings;
99
1010struct KernelAllocator ;
1111
12+ /// Calls `krealloc` with a proper size to alloc a new object aligned to `new_layout`'s alignment.
13+ ///
14+ /// # Safety
15+ ///
16+ /// - `ptr` can be either null or a pointer which has been allocated by this allocator.
17+ /// - `new_layout` must have a non-zero size.
18+ unsafe fn krealloc_aligned ( ptr : * mut u8 , new_layout : Layout , flags : bindings:: gfp_t ) -> * mut u8 {
19+ // Customized layouts from `Layout::from_size_align()` can have size < align, so pad first.
20+ let layout = new_layout. pad_to_align ( ) ;
21+
22+ let mut size = layout. size ( ) ;
23+
24+ if layout. align ( ) > bindings:: BINDINGS_ARCH_SLAB_MINALIGN {
25+ // The alignment requirement exceeds the slab guarantee, thus try to enlarge the size
26+ // to use the "power-of-two" size/alignment guarantee (see comments in `kmalloc()` for
27+ // more information).
28+ //
29+ // Note that `layout.size()` (after padding) is guaranteed to be a multiple of
30+ // `layout.align()`, so `next_power_of_two` gives enough alignment guarantee.
31+ size = size. next_power_of_two ( ) ;
32+ }
33+
34+ // SAFETY:
35+ // - `ptr` is either null or a pointer returned from a previous `k{re}alloc()` by the
36+ // function safety requirement.
37+ // - `size` is greater than 0 since it's either a `layout.size()` (which cannot be zero
38+ // according to the function safety requirement) or a result from `next_power_of_two()`.
39+ unsafe { bindings:: krealloc ( ptr as * const core:: ffi:: c_void , size, flags) as * mut u8 }
40+ }
41+
1242unsafe impl GlobalAlloc for KernelAllocator {
1343 unsafe fn alloc ( & self , layout : Layout ) -> * mut u8 {
1444 // `krealloc()` is used instead of `kmalloc()` because the latter is
@@ -30,10 +60,20 @@ static ALLOCATOR: KernelAllocator = KernelAllocator;
3060// to extract the object file that has them from the archive. For the moment,
3161// let's generate them ourselves instead.
3262//
63+ // Note: Although these are *safe* functions, they are called by the compiler
64+ // with parameters that obey the same `GlobalAlloc` function safety
65+ // requirements: size and align should form a valid layout, and size is
66+ // greater than 0.
67+ //
3368// Note that `#[no_mangle]` implies exported too, nowadays.
3469#[ no_mangle]
35- fn __rust_alloc ( size : usize , _align : usize ) -> * mut u8 {
36- unsafe { bindings:: krealloc ( core:: ptr:: null ( ) , size, bindings:: GFP_KERNEL ) as * mut u8 }
70+ fn __rust_alloc ( size : usize , align : usize ) -> * mut u8 {
71+ // SAFETY: See assumption above.
72+ let layout = unsafe { Layout :: from_size_align_unchecked ( size, align) } ;
73+
74+ // SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater
75+ // than 0.
76+ unsafe { krealloc_aligned ( ptr:: null_mut ( ) , layout, bindings:: GFP_KERNEL ) }
3777}
3878
3979#[ no_mangle]
@@ -42,23 +82,27 @@ fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) {
4282}
4383
4484#[ no_mangle]
45- fn __rust_realloc ( ptr : * mut u8 , _old_size : usize , _align : usize , new_size : usize ) -> * mut u8 {
46- unsafe {
47- bindings:: krealloc (
48- ptr as * const core:: ffi:: c_void ,
49- new_size,
50- bindings:: GFP_KERNEL ,
51- ) as * mut u8
52- }
85+ fn __rust_realloc ( ptr : * mut u8 , _old_size : usize , align : usize , new_size : usize ) -> * mut u8 {
86+ // SAFETY: See assumption above.
87+ let new_layout = unsafe { Layout :: from_size_align_unchecked ( new_size, align) } ;
88+
89+ // SAFETY: Per assumption above, `ptr` is allocated by `__rust_*` before, and the size of
90+ // `new_layout` is greater than 0.
91+ unsafe { krealloc_aligned ( ptr, new_layout, bindings:: GFP_KERNEL ) }
5392}
5493
5594#[ no_mangle]
56- fn __rust_alloc_zeroed ( size : usize , _align : usize ) -> * mut u8 {
95+ fn __rust_alloc_zeroed ( size : usize , align : usize ) -> * mut u8 {
96+ // SAFETY: See assumption above.
97+ let layout = unsafe { Layout :: from_size_align_unchecked ( size, align) } ;
98+
99+ // SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater
100+ // than 0.
57101 unsafe {
58- bindings :: krealloc (
59- core :: ptr:: null ( ) ,
60- size ,
102+ krealloc_aligned (
103+ ptr:: null_mut ( ) ,
104+ layout ,
61105 bindings:: GFP_KERNEL | bindings:: __GFP_ZERO,
62- ) as * mut u8
106+ )
63107 }
64108}
0 commit comments