allocator.rs (e75850b4573a092078d5ff1493d3d9ee16b98821) allocator.rs (89eed1ab1161e7d60595917e3b982e03dfcc0f8d)
1// SPDX-License-Identifier: GPL-2.0
2
3//! Allocator support.
4
5use core::alloc::{GlobalAlloc, Layout};
6use core::ptr;
7
8use crate::bindings;

--- 27 unchanged lines hidden (view full) ---

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
42unsafe impl GlobalAlloc for KernelAllocator {
43 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
1// SPDX-License-Identifier: GPL-2.0
2
3//! Allocator support.
4
5use core::alloc::{GlobalAlloc, Layout};
6use core::ptr;
7
8use crate::bindings;

--- 27 unchanged lines hidden (view full) ---

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
42unsafe impl GlobalAlloc for KernelAllocator {
43 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
44 // `krealloc()` is used instead of `kmalloc()` because the latter is
45 // an inline function and cannot be bound to as a result.
46 unsafe { bindings::krealloc(ptr::null(), layout.size(), bindings::GFP_KERNEL) as *mut u8 }
44 // SAFETY: `ptr::null_mut()` is null and `layout` has a non-zero size by the function safety
45 // requirement.
46 unsafe { krealloc_aligned(ptr::null_mut(), layout, bindings::GFP_KERNEL) }
47 }
48
49 unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
50 unsafe {
51 bindings::kfree(ptr as *const core::ffi::c_void);
52 }
53 }
47 }
48
49 unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
50 unsafe {
51 bindings::kfree(ptr as *const core::ffi::c_void);
52 }
53 }
54}
55
54
56#[global_allocator]
57static ALLOCATOR: KernelAllocator = KernelAllocator;
55 unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
56 // SAFETY:
57 // - `new_size`, when rounded up to the nearest multiple of `layout.align()`, will not
58 // overflow `isize` by the function safety requirement.
59 // - `layout.align()` is a proper alignment (i.e. not zero and must be a power of two).
60 let layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) };
58
61
59// `rustc` only generates these for some crate types. Even then, we would need
60// to extract the object file that has them from the archive. For the moment,
61// let's generate them ourselves instead.
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//
68// Note that `#[no_mangle]` implies exported too, nowadays.
69#[no_mangle]
70fn __rust_alloc(size: usize, align: usize) -> *mut u8 {
71 // SAFETY: See assumption above.
72 let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
62 // SAFETY:
63 // - `ptr` is either null or a pointer allocated by this allocator by the function safety
64 // requirement.
65 // - the size of `layout` is not zero because `new_size` is not zero by the function safety
66 // requirement.
67 unsafe { krealloc_aligned(ptr, layout, bindings::GFP_KERNEL) }
68 }
73
69
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) }
70 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
71 // SAFETY: `ptr::null_mut()` is null and `layout` has a non-zero size by the function safety
72 // requirement.
73 unsafe {
74 krealloc_aligned(
75 ptr::null_mut(),
76 layout,
77 bindings::GFP_KERNEL | bindings::__GFP_ZERO,
78 )
79 }
80 }
77}
78
81}
82
79#[no_mangle]
80fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) {
81 unsafe { bindings::kfree(ptr as *const core::ffi::c_void) };
82}
83#[global_allocator]
84static ALLOCATOR: KernelAllocator = KernelAllocator;
83
85
86// See <https://github.com/rust-lang/rust/pull/86844>.
84#[no_mangle]
87#[no_mangle]
85fn __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) }
92}
93
94#[no_mangle]
95fn __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.
101 unsafe {
102 krealloc_aligned(
103 ptr::null_mut(),
104 layout,
105 bindings::GFP_KERNEL | bindings::__GFP_ZERO,
106 )
107 }
108}
88static __rust_no_alloc_shim_is_unstable: u8 = 0;