@@ -9,6 +9,36 @@ use crate::bindings;
9
9
10
10
struct KernelAllocator ;
11
11
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
+
12
42
unsafe impl GlobalAlloc for KernelAllocator {
13
43
unsafe fn alloc ( & self , layout : Layout ) -> * mut u8 {
14
44
// `krealloc()` is used instead of `kmalloc()` because the latter is
@@ -30,10 +60,20 @@ static ALLOCATOR: KernelAllocator = KernelAllocator;
30
60
// to extract the object file that has them from the archive. For the moment,
31
61
// let's generate them ourselves instead.
32
62
//
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
+ //
33
68
// Note that `#[no_mangle]` implies exported too, nowadays.
34
69
#[ 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 ) }
37
77
}
38
78
39
79
#[ no_mangle]
@@ -42,23 +82,27 @@ fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) {
42
82
}
43
83
44
84
#[ 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 ) }
53
92
}
54
93
55
94
#[ 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.
57
101
unsafe {
58
- bindings :: krealloc (
59
- core :: ptr:: null ( ) ,
60
- size ,
102
+ krealloc_aligned (
103
+ ptr:: null_mut ( ) ,
104
+ layout ,
61
105
bindings:: GFP_KERNEL | bindings:: __GFP_ZERO,
62
- ) as * mut u8
106
+ )
63
107
}
64
108
}
0 commit comments