Pull rust updates from Miguel Ojeda: "Toolchain and infrastructure: - Derive 'Zeroable' for all structs and unions generated by 'bindgen' where possible and corresponding cleanups. To do so, add the 'pin-init' crate as a dependency to 'bindings' and 'uapi'. It also includes its first use in the 'cpufreq' module, with more to come in the next cycle. - Add warning to the 'rustdoc' target to detect broken 'srctree/' links and fix existing cases. - Remove support for unused (since v6.16) host '#[test]'s, simplifying the 'rusttest' target. Tests should generally run within KUnit. 'kernel' crate: - Add 'ptr' module with a new 'Alignment' type, which is always a power of two and is used to validate that a given value is a valid alignment and to perform masking and alignment operations: // Checked at build time. assert_eq!(Alignment::new::<16>().as_usize(), 16); // Checked at runtime. assert_eq!(Alignment::new_checked(15), None); assert_eq!(Alignment::of::<u8>().log2(), 0); assert_eq!(0x25u8.align_down(Alignment::new::<0x10>()), 0x20); assert_eq!(0x5u8.align_up(Alignment::new::<0x10>()), Some(0x10)); assert_eq!(u8::MAX.align_up(Alignment::new::<0x10>()), None); It also includes its first use in Nova. - Add 'core::mem::{align,size}_of{,_val}' to the prelude, matching Rust 1.80.0. - Keep going with the steps on our migration to the standard library 'core::ffi::CStr' type (use 'kernel::{fmt, prelude::fmt!}' and use upstream method names). - 'error' module: improve 'Error::from_errno' and 'to_result' documentation, including examples/tests. - 'sync' module: extend 'aref' submodule documentation now that it exists, and more updates to complete the ongoing move of 'ARef' and 'AlwaysRefCounted' to 'sync::aref'. - 'list' module: add an example/test for 'ListLinksSelfPtr' usage. - 'alloc' module: - Implement 'Box::pin_slice()', which constructs a pinned slice of elements. - Provide information about the minimum alignment guarantees of 'Kmalloc', 'Vmalloc' and 'KVmalloc'. - Take minimum alignment guarantees of allocators for 'ForeignOwnable' into account. - Remove the 'allocator_test' (including 'Cmalloc'). - Add doctest for 'Vec::as_slice()'. - Constify various methods. - 'time' module: - Add methods on 'HrTimer' that can only be called with exclusive access to an unarmed timer, or from timer callback context. - Add arithmetic operations to 'Instant' and 'Delta'. - Add a few convenience and access methods to 'HrTimer' and 'Instant'. 'macros' crate: - Reduce collections in 'quote!' macro. And a few other cleanups and improvements" * tag 'rust-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux: (58 commits) gpu: nova-core: use Alignment for alignment-related operations rust: add `Alignment` type rust: macros: reduce collections in `quote!` macro rust: acpi: use `core::ffi::CStr` method names rust: of: use `core::ffi::CStr` method names rust: net: use `core::ffi::CStr` method names rust: miscdevice: use `core::ffi::CStr` method names rust: kunit: use `core::ffi::CStr` method names rust: firmware: use `core::ffi::CStr` method names rust: drm: use `core::ffi::CStr` method names rust: cpufreq: use `core::ffi::CStr` method names rust: configfs: use `core::ffi::CStr` method names rust: auxiliary: use `core::ffi::CStr` method names drm/panic: use `core::ffi::CStr` method names rust: device: use `kernel::{fmt,prelude::fmt!}` rust: sync: use `kernel::{fmt,prelude::fmt!}` rust: seq_file: use `kernel::{fmt,prelude::fmt!}` rust: kunit: use `kernel::{fmt,prelude::fmt!}` rust: file: use `kernel::{fmt,prelude::fmt!}` rust: device: use `kernel::{fmt,prelude::fmt!}` ...
Unified · Split
| @@ -147,7 +147,6 @@ Numerical operations [NUMM] · 146 unmodified lines | ||
| 147 | 147 | Nova uses integer operations that are not part of the standard library (or not |
| 148 | 148 | implemented in an optimized way for the kernel). These include: |
| 149 | 149 | |
| 150 | −- Aligning up and down to a power of two, | |
| 151 | 150 | - The "Find Last Set Bit" (`fls` function of the C part of the kernel) |
| 152 | 151 | operation. |
| 153 | 152 | |
| @@ -51,7 +51,7 @@ impl kernel::InPlaceModule for NullBlkModule { · 50 unmodified lines | ||
| 51 | 51 | .logical_block_size(4096)? |
| 52 | 52 | .physical_block_size(4096)? |
| 53 | 53 | .rotational(false) |
| 54 | − .build(format_args!("rnullb{}", 0), tagset) | |
| 54 | + .build(fmt!("rnullb{}", 0), tagset) | |
| 55 | 55 | })(); |
| 56 | 56 | |
| 57 | 57 | try_pin_init!(Self { |
| @@ -968,7 +968,7 @@ pub unsafe extern "C" fn drm_panic_qr_generate( · 967 unmodified lines | ||
| 968 | 968 | // nul-terminated string. |
| 969 | 969 | let url_cstr: &CStr = unsafe { CStr::from_char_ptr(url) }; |
| 970 | 970 | let segments = &[ |
| 971 | − &Segment::Binary(url_cstr.as_bytes()), | |
| 971 | + &Segment::Binary(url_cstr.to_bytes()), | |
| 972 | 972 | &Segment::Numeric(&data_slice[0..data_len]), |
| 973 | 973 | ]; |
| 974 | 974 | match EncodedMsg::new(segments, tmp_slice) { |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | use core::ops::Range; |
| 4 | 4 | |
| 5 | 5 | use kernel::prelude::*; |
| 6 | +use kernel::ptr::{Alignable, Alignment}; | |
| 6 | 7 | use kernel::sizes::*; |
| 7 | 8 | use kernel::types::ARef; |
| 8 | 9 | use kernel::{dev_warn, device}; |
| @@ -130,10 +131,9 @@ impl FbLayout { · 121 unmodified lines | ||
| 130 | 131 | }; |
| 131 | 132 | |
| 132 | 133 | let frts = { |
| 133 | − const FRTS_DOWN_ALIGN: u64 = SZ_128K as u64; | |
| 134 | + const FRTS_DOWN_ALIGN: Alignment = Alignment::new::<SZ_128K>(); | |
| 134 | 135 | const FRTS_SIZE: u64 = SZ_1M as u64; |
| 135 | − // TODO[NUMM]: replace with `align_down` once it lands. | |
| 136 | − let frts_base = (vga_workspace.start & !(FRTS_DOWN_ALIGN - 1)) - FRTS_SIZE; | |
| 136 | + let frts_base = vga_workspace.start.align_down(FRTS_DOWN_ALIGN) - FRTS_SIZE; | |
| 137 | 137 | |
| 138 | 138 | frts_base..frts_base + FRTS_SIZE |
| 139 | 139 | }; |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | |
| 3 | −use kernel::{device, devres::Devres, error::code::*, pci, prelude::*, sync::Arc}; | |
| 3 | +use kernel::{device, devres::Devres, error::code::*, fmt, pci, prelude::*, sync::Arc}; | |
| 4 | 4 | |
| 5 | 5 | use crate::driver::Bar0; |
| 6 | 6 | use crate::falcon::{gsp::Gsp, sec2::Sec2, Falcon}; |
| @@ -12,7 +12,6 @@ use crate::gfw; · 5 unmodified lines | ||
| 12 | 12 | use crate::regs; |
| 13 | 13 | use crate::util; |
| 14 | 14 | use crate::vbios::Vbios; |
| 15 | −use core::fmt; | |
| 16 | 15 | |
| 17 | 16 | macro_rules! define_chipset { |
| 18 | 17 | ({ $($variant:ident = $value:expr),* $(,)* }) => |
| @@ -149,10 +149,10 @@ macro_rules! register { · 148 unmodified lines | ||
| 149 | 149 | |
| 150 | 150 | // TODO[REGA]: display the raw hex value, then the value of all the fields. This requires |
| 151 | 151 | // matching the fields, which will complexify the syntax considerably... |
| 152 | − impl ::core::fmt::Debug for $name { | |
| 153 | − fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { | |
| 152 | + impl ::kernel::fmt::Debug for $name { | |
| 153 | + fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result { | |
| 154 | 154 | f.debug_tuple(stringify!($name)) |
| 155 | − .field(&format_args!("0x{0:x}", &self.0)) | |
| 155 | + .field(&::kernel::prelude::fmt!("0x{0:x}", &self.0)) | |
| 156 | 156 | .finish() |
| 157 | 157 | } |
| 158 | 158 | } |
| @@ -10,6 +10,7 @@ use kernel::device; · 9 unmodified lines | ||
| 10 | 10 | use kernel::error::Result; |
| 11 | 11 | use kernel::pci; |
| 12 | 12 | use kernel::prelude::*; |
| 13 | +use kernel::ptr::{Alignable, Alignment}; | |
| 13 | 14 | |
| 14 | 15 | /// The offset of the VBIOS ROM in the BAR0 space. |
| 15 | 16 | const ROM_OFFSET: usize = 0x300000; |
| @@ -177,8 +178,7 @@ impl<'a> Iterator for VbiosIterator<'a> { · 161 unmodified lines | ||
| 177 | 178 | |
| 178 | 179 | // Advance to next image (aligned to 512 bytes). |
| 179 | 180 | self.current_offset += image_size; |
| 180 | − // TODO[NUMM]: replace with `align_up` once it lands. | |
| 181 | − self.current_offset = self.current_offset.next_multiple_of(512); | |
| 181 | + self.current_offset = self.current_offset.align_up(Alignment::new::<512>())?; | |
| 182 | 182 | |
| 183 | 183 | Some(Ok(full_image)) |
| 184 | 184 | } |
| @@ -98,6 +98,12 @@ quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< · 97 unmodified lines | ||
| 98 | 98 | # and then retouch the generated files. |
| 99 | 99 | rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \ |
| 100 | 100 | rustdoc-kernel rustdoc-pin_init |
| 101 | + $(Q)grep -Ehro '<a href="srctree/([^"]+)"' $(rustdoc_output) | \ | |
| 102 | + cut -d'"' -f2 | cut -d/ -f2- | while read f; do \ | |
| 103 | + if [ ! -e "$(srctree)/$$f" ]; then \ | |
| 104 | + echo "warning: srctree/ link to $$f does not exist"; \ | |
| 105 | + fi \ | |
| 106 | + done | |
| 101 | 107 | $(Q)cp $(srctree)/Documentation/images/logo.svg $(rustdoc_output)/static.files/ |
| 102 | 108 | $(Q)cp $(srctree)/Documentation/images/COPYING-logo $(rustdoc_output)/static.files/ |
| 103 | 109 | $(Q)find $(rustdoc_output) -name '*.html' -type f -print0 | xargs -0 sed -Ei \ |
| @@ -193,12 +199,12 @@ rusttestlib-kernel: $(src)/kernel/lib.rs rusttestlib-bindings rusttestlib-uapi \ · 89 unmodified lines | ||
| 193 | 199 | $(obj)/bindings.o FORCE |
| 194 | 200 | +$(call if_changed,rustc_test_library) |
| 195 | 201 | |
| 196 | −rusttestlib-bindings: private rustc_target_flags = --extern ffi | |
| 197 | −rusttestlib-bindings: $(src)/bindings/lib.rs rusttestlib-ffi FORCE | |
| 202 | +rusttestlib-bindings: private rustc_target_flags = --extern ffi --extern pin_init | |
| 203 | +rusttestlib-bindings: $(src)/bindings/lib.rs rusttestlib-ffi rusttestlib-pin_init FORCE | |
| 198 | 204 | +$(call if_changed,rustc_test_library) |
| 199 | 205 | |
| 200 | −rusttestlib-uapi: private rustc_target_flags = --extern ffi | |
| 201 | −rusttestlib-uapi: $(src)/uapi/lib.rs rusttestlib-ffi FORCE | |
| 206 | +rusttestlib-uapi: private rustc_target_flags = --extern ffi --extern pin_init | |
| 207 | +rusttestlib-uapi: $(src)/uapi/lib.rs rusttestlib-ffi rusttestlib-pin_init FORCE | |
| 202 | 208 | +$(call if_changed,rustc_test_library) |
| 203 | 209 | |
| 204 | 210 | quiet_cmd_rustdoc_test = RUSTDOC T $< |
| @@ -248,7 +254,7 @@ quiet_cmd_rustc_test = $(RUSTC_OR_CLIPPY_QUIET) T $< · 43 unmodified lines | ||
| 248 | 254 | $(objtree)/$(obj)/test/$(subst rusttest-,,$@) $(rust_test_quiet) \ |
| 249 | 255 | $(rustc_test_run_flags) |
| 250 | 256 | |
| 251 | −rusttest: rusttest-macros rusttest-kernel | |
| 257 | +rusttest: rusttest-macros | |
| 252 | 258 | |
| 253 | 259 | rusttest-macros: private rustc_target_flags = --extern proc_macro \ |
| 254 | 260 | --extern macros --extern kernel --extern pin_init |
| @@ -258,13 +264,6 @@ rusttest-macros: $(src)/macros/lib.rs \ · 3 unmodified lines | ||
| 258 | 264 | +$(call if_changed,rustc_test) |
| 259 | 265 | +$(call if_changed,rustdoc_test) |
| 260 | 266 | |
| 261 | −rusttest-kernel: private rustc_target_flags = --extern ffi --extern pin_init \ | |
| 262 | − --extern build_error --extern macros --extern bindings --extern uapi | |
| 263 | −rusttest-kernel: $(src)/kernel/lib.rs rusttestlib-ffi rusttestlib-kernel \ | |
| 264 | − rusttestlib-build_error rusttestlib-macros rusttestlib-bindings \ | |
| 265 | − rusttestlib-uapi rusttestlib-pin_init FORCE | |
| 266 | − +$(call if_changed,rustc_test) | |
| 267 | − | |
| 268 | 267 | ifdef CONFIG_CC_IS_CLANG |
| 269 | 268 | bindgen_c_flags = $(c_flags) |
| 270 | 269 | else |
| @@ -531,17 +530,19 @@ $(obj)/ffi.o: private skip_gendwarfksyms = 1 · 260 unmodified lines | ||
| 531 | 530 | $(obj)/ffi.o: $(src)/ffi.rs $(obj)/compiler_builtins.o FORCE |
| 532 | 531 | +$(call if_changed_rule,rustc_library) |
| 533 | 532 | |
| 534 | −$(obj)/bindings.o: private rustc_target_flags = --extern ffi | |
| 533 | +$(obj)/bindings.o: private rustc_target_flags = --extern ffi --extern pin_init | |
| 535 | 534 | $(obj)/bindings.o: $(src)/bindings/lib.rs \ |
| 536 | 535 | $(obj)/ffi.o \ |
| 536 | + $(obj)/pin_init.o \ | |
| 537 | 537 | $(obj)/bindings/bindings_generated.rs \ |
| 538 | 538 | $(obj)/bindings/bindings_helpers_generated.rs FORCE |
| 539 | 539 | +$(call if_changed_rule,rustc_library) |
| 540 | 540 | |
| 541 | −$(obj)/uapi.o: private rustc_target_flags = --extern ffi | |
| 541 | +$(obj)/uapi.o: private rustc_target_flags = --extern ffi --extern pin_init | |
| 542 | 542 | $(obj)/uapi.o: private skip_gendwarfksyms = 1 |
| 543 | 543 | $(obj)/uapi.o: $(src)/uapi/lib.rs \ |
| 544 | 544 | $(obj)/ffi.o \ |
| 545 | + $(obj)/pin_init.o \ | |
| 545 | 546 | $(obj)/uapi/uapi_generated.rs FORCE |
| 546 | 547 | +$(call if_changed_rule,rustc_library) |
| 547 | 548 | |
| @@ -34,3 +34,8 @@ · 33 unmodified lines | ||
| 34 | 34 | # We use const helpers to aid bindgen, to avoid conflicts when constants are |
| 35 | 35 | # recognized, block generation of the non-helper constants. |
| 36 | 36 | --blocklist-item ARCH_SLAB_MINALIGN |
| 37 | +--blocklist-item ARCH_KMALLOC_MINALIGN | |
| 38 | + | |
| 39 | +# Structs should implement `Zeroable` when all of their fields do. | |
| 40 | +--with-derive-custom-struct .*=MaybeZeroable | |
| 41 | +--with-derive-custom-union .*=MaybeZeroable | |
| @@ -84,6 +84,7 @@ · 83 unmodified lines | ||
| 84 | 84 | |
| 85 | 85 | /* `bindgen` gets confused at certain things. */ |
| 86 | 86 | const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; |
| 87 | +const size_t RUST_CONST_HELPER_ARCH_KMALLOC_MINALIGN = ARCH_KMALLOC_MINALIGN; | |
| 87 | 88 | const size_t RUST_CONST_HELPER_PAGE_SIZE = PAGE_SIZE; |
| 88 | 89 | const gfp_t RUST_CONST_HELPER_GFP_ATOMIC = GFP_ATOMIC; |
| 89 | 90 | const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL; |
| @@ -31,11 +31,19 @@ · 30 unmodified lines | ||
| 31 | 31 | #[allow(clippy::undocumented_unsafe_blocks)] |
| 32 | 32 | #[cfg_attr(CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES, allow(unnecessary_transmutes))] |
| 33 | 33 | mod bindings_raw { |
| 34 | + use pin_init::{MaybeZeroable, Zeroable}; | |
| 35 | + | |
| 34 | 36 | // Manual definition for blocklisted types. |
| 35 | 37 | type __kernel_size_t = usize; |
| 36 | 38 | type __kernel_ssize_t = isize; |
| 37 | 39 | type __kernel_ptrdiff_t = isize; |
| 38 | 40 | |
| 41 | + // `bindgen` doesn't automatically do this, see | |
| 42 | + // <https://github.com/rust-lang/rust-bindgen/issues/3196> | |
| 43 | + // | |
| 44 | + // SAFETY: `__BindgenBitfieldUnit<Storage>` is a newtype around `Storage`. | |
| 45 | + unsafe impl<Storage> Zeroable for __BindgenBitfieldUnit<Storage> where Storage: Zeroable {} | |
| 46 | + | |
| 39 | 47 | // Use glob import here to expose all helpers. |
| 40 | 48 | // Symbols defined within the module will take precedence to the glob import. |
| 41 | 49 | pub use super::bindings_helper::*; |
| @@ -37,11 +37,8 @@ impl DeviceId { · 36 unmodified lines | ||
| 37 | 37 | /// Create a new device id from an ACPI 'id' string. |
| 38 | 38 | #[inline(always)] |
| 39 | 39 | pub const fn new(id: &'static CStr) -> Self { |
| 40 | − build_assert!( | |
| 41 | − id.len_with_nul() <= Self::ACPI_ID_LEN, | |
| 42 | − "ID exceeds 16 bytes" | |
| 43 | − ); | |
| 44 | − let src = id.as_bytes_with_nul(); | |
| 40 | + let src = id.to_bytes_with_nul(); | |
| 41 | + build_assert!(src.len() <= Self::ACPI_ID_LEN, "ID exceeds 16 bytes"); | |
| 45 | 42 | // Replace with `bindings::acpi_device_id::default()` once stabilized for `const`. |
| 46 | 43 | // SAFETY: FFI type is valid to be zero-initialized. |
| 47 | 44 | let mut acpi: bindings::acpi_device_id = unsafe { core::mem::zeroed() }; |
| @@ -2,18 +2,11 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | //! Implementation of the kernel's memory allocation infrastructure. |
| 4 | 4 | |
| 5 | −#[cfg(not(any(test, testlib)))] | |
| 6 | 5 | pub mod allocator; |
| 7 | 6 | pub mod kbox; |
| 8 | 7 | pub mod kvec; |
| 9 | 8 | pub mod layout; |
| 10 | 9 | |
| 11 | −#[cfg(any(test, testlib))] | |
| 12 | −pub mod allocator_test; | |
| 13 | − | |
| 14 | −#[cfg(any(test, testlib))] | |
| 15 | −pub use self::allocator_test as allocator; | |
| 16 | − | |
| 17 | 10 | pub use self::kbox::Box; |
| 18 | 11 | pub use self::kbox::KBox; |
| 19 | 12 | pub use self::kbox::KVBox; |
| @@ -137,6 +130,14 @@ pub mod flags { · 117 unmodified lines | ||
| 137 | 130 | /// - Implementers must ensure that all trait functions abide by the guarantees documented in the |
| 138 | 131 | /// `# Guarantees` sections. |
| 139 | 132 | pub unsafe trait Allocator { |
| 133 | + /// The minimum alignment satisfied by all allocations from this allocator. | |
| 134 | + /// | |
| 135 | + /// # Guarantees | |
| 136 | + /// | |
| 137 | + /// Any pointer allocated by this allocator is guaranteed to be aligned to `MIN_ALIGN` even if | |
| 138 | + /// the requested layout has a smaller alignment. | |
| 139 | + const MIN_ALIGN: usize; | |
| 140 | + | |
| 140 | 141 | /// Allocate memory based on `layout` and `flags`. |
| 141 | 142 | /// |
| 142 | 143 | /// On success, returns a buffer represented as `NonNull<[u8]>` that satisfies the layout |
| @@ -17,6 +17,8 @@ use crate::alloc::{AllocError, Allocator}; · 16 unmodified lines | ||
| 17 | 17 | use crate::bindings; |
| 18 | 18 | use crate::pr_warn; |
| 19 | 19 | |
| 20 | +const ARCH_KMALLOC_MINALIGN: usize = bindings::ARCH_KMALLOC_MINALIGN; | |
| 21 | + | |
| 20 | 22 | /// The contiguous kernel allocator. |
| 21 | 23 | /// |
| 22 | 24 | /// `Kmalloc` is typically used for physically contiguous allocations up to page size, but also |
| @@ -128,6 +130,8 @@ impl Kmalloc { · 105 unmodified lines | ||
| 128 | 130 | // - passing a pointer to a valid memory allocation is OK, |
| 129 | 131 | // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same. |
| 130 | 132 | unsafe impl Allocator for Kmalloc { |
| 133 | + const MIN_ALIGN: usize = ARCH_KMALLOC_MINALIGN; | |
| 134 | + | |
| 131 | 135 | #[inline] |
| 132 | 136 | unsafe fn realloc( |
| 133 | 137 | ptr: Option<NonNull<u8>>, |
| @@ -147,6 +151,8 @@ unsafe impl Allocator for Kmalloc { · 13 unmodified lines | ||
| 147 | 151 | // - passing a pointer to a valid memory allocation is OK, |
| 148 | 152 | // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same. |
| 149 | 153 | unsafe impl Allocator for Vmalloc { |
| 154 | + const MIN_ALIGN: usize = kernel::page::PAGE_SIZE; | |
| 155 | + | |
| 150 | 156 | #[inline] |
| 151 | 157 | unsafe fn realloc( |
| 152 | 158 | ptr: Option<NonNull<u8>>, |
| @@ -171,6 +177,8 @@ unsafe impl Allocator for Vmalloc { · 18 unmodified lines | ||
| 171 | 177 | // - passing a pointer to a valid memory allocation is OK, |
| 172 | 178 | // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same. |
| 173 | 179 | unsafe impl Allocator for KVmalloc { |
| 180 | + const MIN_ALIGN: usize = ARCH_KMALLOC_MINALIGN; | |
| 181 | + | |
| 174 | 182 | #[inline] |
| 175 | 183 | unsafe fn realloc( |
| 176 | 184 | ptr: Option<NonNull<u8>>, |
| @@ -1,124 +0,0 @@ | ||
| 1 | −// SPDX-License-Identifier: GPL-2.0 | |
| 2 | − | |
| 3 | −//! So far the kernel's `Box` and `Vec` types can't be used by userspace test cases, since all users | |
| 4 | −//! of those types (e.g. `CString`) use kernel allocators for instantiation. | |
| 5 | −//! | |
| 6 | −//! In order to allow userspace test cases to make use of such types as well, implement the | |
| 7 | −//! `Cmalloc` allocator within the `allocator_test` module and type alias all kernel allocators to | |
| 8 | −//! `Cmalloc`. The `Cmalloc` allocator uses libc's `realloc()` function as allocator backend. | |
| 9 | − | |
| 10 | −#![allow(missing_docs)] | |
| 11 | − | |
| 12 | −use super::{flags::*, AllocError, Allocator, Flags}; | |
| 13 | −use core::alloc::Layout; | |
| 14 | −use core::cmp; | |
| 15 | −use core::ptr; | |
| 16 | −use core::ptr::NonNull; | |
| 17 | − | |
| 18 | −/// The userspace allocator based on libc. | |
| 19 | −pub struct Cmalloc; | |
| 20 | − | |
| 21 | −pub type Kmalloc = Cmalloc; | |
| 22 | −pub type Vmalloc = Kmalloc; | |
| 23 | −pub type KVmalloc = Kmalloc; | |
| 24 | − | |
| 25 | −impl Cmalloc { | |
| 26 | − /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of | |
| 27 | − /// `layout`. | |
| 28 | − pub fn aligned_layout(layout: Layout) -> Layout { | |
| 29 | − // Note that `layout.size()` (after padding) is guaranteed to be a multiple of | |
| 30 | − // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return | |
| 31 | − // a properly aligned object (see comments in `kmalloc()` for more information). | |
| 32 | − layout.pad_to_align() | |
| 33 | − } | |
| 34 | −} | |
| 35 | − | |
| 36 | −extern "C" { | |
| 37 | − #[link_name = "aligned_alloc"] | |
| 38 | − fn libc_aligned_alloc(align: usize, size: usize) -> *mut crate::ffi::c_void; | |
| 39 | − | |
| 40 | − #[link_name = "free"] | |
| 41 | − fn libc_free(ptr: *mut crate::ffi::c_void); | |
| 42 | −} | |
| 43 | − | |
| 44 | −// SAFETY: | |
| 45 | −// - memory remains valid until it is explicitly freed, | |
| 46 | −// - passing a pointer to a valid memory allocation created by this `Allocator` is always OK, | |
| 47 | −// - `realloc` provides the guarantees as provided in the `# Guarantees` section. | |
| 48 | −unsafe impl Allocator for Cmalloc { | |
| 49 | − unsafe fn realloc( | |
| 50 | − ptr: Option<NonNull<u8>>, | |
| 51 | − layout: Layout, | |
| 52 | − old_layout: Layout, | |
| 53 | − flags: Flags, | |
| 54 | − ) -> Result<NonNull<[u8]>, AllocError> { | |
| 55 | − let src = match ptr { | |
| 56 | − Some(src) => { | |
| 57 | − if old_layout.size() == 0 { | |
| 58 | − ptr::null_mut() | |
| 59 | − } else { | |
| 60 | − src.as_ptr() | |
| 61 | − } | |
| 62 | − } | |
| 63 | − None => ptr::null_mut(), | |
| 64 | − }; | |
| 65 | − | |
| 66 | − if layout.size() == 0 { | |
| 67 | − // SAFETY: `src` is either NULL or was previously allocated with this `Allocator` | |
| 68 | − unsafe { libc_free(src.cast()) }; | |
| 69 | − | |
| 70 | − return Ok(NonNull::slice_from_raw_parts( | |
| 71 | − crate::alloc::dangling_from_layout(layout), | |
| 72 | − 0, | |
| 73 | − )); | |
| 74 | − } | |
| 75 | − | |
| 76 | − // ISO C (ISO/IEC 9899:2011) defines `aligned_alloc`: | |
| 77 | − // | |
| 78 | − // > The value of alignment shall be a valid alignment supported by the implementation | |
| 79 | − // [...]. | |
| 80 | − // | |
| 81 | − // As an example of the "supported by the implementation" requirement, POSIX.1-2001 (IEEE | |
| 82 | − // 1003.1-2001) defines `posix_memalign`: | |
| 83 | − // | |
| 84 | − // > The value of alignment shall be a power of two multiple of sizeof (void *). | |
| 85 | − // | |
| 86 | − // and POSIX-based implementations of `aligned_alloc` inherit this requirement. At the time | |
| 87 | − // of writing, this is known to be the case on macOS (but not in glibc). | |
| 88 | − // | |
| 89 | − // Satisfy the stricter requirement to avoid spurious test failures on some platforms. | |
| 90 | − let min_align = core::mem::size_of::<*const crate::ffi::c_void>(); | |
| 91 | − let layout = layout.align_to(min_align).map_err(|_| AllocError)?; | |
| 92 | − let layout = layout.pad_to_align(); | |
| 93 | − | |
| 94 | − // SAFETY: Returns either NULL or a pointer to a memory allocation that satisfies or | |
| 95 | − // exceeds the given size and alignment requirements. | |
| 96 | − let dst = unsafe { libc_aligned_alloc(layout.align(), layout.size()) }.cast::<u8>(); | |
| 97 | − let dst = NonNull::new(dst).ok_or(AllocError)?; | |
| 98 | − | |
| 99 | − if flags.contains(__GFP_ZERO) { | |
| 100 | − // SAFETY: The preceding calls to `libc_aligned_alloc` and `NonNull::new` | |
| 101 | − // guarantee that `dst` points to memory of at least `layout.size()` bytes. | |
| 102 | − unsafe { dst.as_ptr().write_bytes(0, layout.size()) }; | |
| 103 | − } | |
| 104 | − | |
| 105 | − if !src.is_null() { | |
| 106 | − // SAFETY: | |
| 107 | − // - `src` has previously been allocated with this `Allocator`; `dst` has just been | |
| 108 | − // newly allocated, hence the memory regions do not overlap. | |
| 109 | − // - both` src` and `dst` are properly aligned and valid for reads and writes | |
| 110 | − unsafe { | |
| 111 | − ptr::copy_nonoverlapping( | |
| 112 | − src, | |
| 113 | − dst.as_ptr(), | |
| 114 | − cmp::min(layout.size(), old_layout.size()), | |
| 115 | − ) | |
| 116 | − }; | |
| 117 | − } | |
| 118 | − | |
| 119 | − // SAFETY: `src` is either NULL or was previously allocated with this `Allocator` | |
| 120 | − unsafe { libc_free(src.cast()) }; | |
| 121 | − | |
| 122 | − Ok(NonNull::slice_from_raw_parts(dst, layout.size())) | |
| 123 | − } | |
| 124 | −} | |
| @@ -7,7 +7,6 @@ use super::allocator::{KVmalloc, Kmalloc, Vmalloc}; · 6 unmodified lines | ||
| 7 | 7 | use super::{AllocError, Allocator, Flags}; |
| 8 | 8 | use core::alloc::Layout; |
| 9 | 9 | use core::borrow::{Borrow, BorrowMut}; |
| 10 | −use core::fmt; | |
| 11 | 10 | use core::marker::PhantomData; |
| 12 | 11 | use core::mem::ManuallyDrop; |
| 13 | 12 | use core::mem::MaybeUninit; |
| @@ -17,6 +16,7 @@ use core::ptr::NonNull; · 3 unmodified lines | ||
| 17 | 16 | use core::result::Result; |
| 18 | 17 | |
| 19 | 18 | use crate::ffi::c_void; |
| 19 | +use crate::fmt; | |
| 20 | 20 | use crate::init::InPlaceInit; |
| 21 | 21 | use crate::types::ForeignOwnable; |
| 22 | 22 | use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption}; |
| @@ -290,6 +290,83 @@ where · 267 unmodified lines | ||
| 290 | 290 | Ok(Self::new(x, flags)?.into()) |
| 291 | 291 | } |
| 292 | 292 | |
| 293 | + /// Construct a pinned slice of elements `Pin<Box<[T], A>>`. | |
| 294 | + /// | |
| 295 | + /// This is a convenient means for creation of e.g. slices of structrures containing spinlocks | |
| 296 | + /// or mutexes. | |
| 297 | + /// | |
| 298 | + /// # Examples | |
| 299 | + /// | |
| 300 | + /// ``` | |
| 301 | + /// use kernel::sync::{new_spinlock, SpinLock}; | |
| 302 | + /// | |
| 303 | + /// struct Inner { | |
| 304 | + /// a: u32, | |
| 305 | + /// b: u32, | |
| 306 | + /// } | |
| 307 | + /// | |
| 308 | + /// #[pin_data] | |
| 309 | + /// struct Example { | |
| 310 | + /// c: u32, | |
| 311 | + /// #[pin] | |
| 312 | + /// d: SpinLock<Inner>, | |
| 313 | + /// } | |
| 314 | + /// | |
| 315 | + /// impl Example { | |
| 316 | + /// fn new() -> impl PinInit<Self, Error> { | |
| 317 | + /// try_pin_init!(Self { | |
| 318 | + /// c: 10, | |
| 319 | + /// d <- new_spinlock!(Inner { a: 20, b: 30 }), | |
| 320 | + /// }) | |
| 321 | + /// } | |
| 322 | + /// } | |
| 323 | + /// | |
| 324 | + /// // Allocate a boxed slice of 10 `Example`s. | |
| 325 | + /// let s = KBox::pin_slice( | |
| 326 | + /// | _i | Example::new(), | |
| 327 | + /// 10, | |
| 328 | + /// GFP_KERNEL | |
| 329 | + /// )?; | |
| 330 | + /// | |
| 331 | + /// assert_eq!(s[5].c, 10); | |
| 332 | + /// assert_eq!(s[3].d.lock().a, 20); | |
| 333 | + /// # Ok::<(), Error>(()) | |
| 334 | + /// ``` | |
| 335 | + pub fn pin_slice<Func, Item, E>( | |
| 336 | + mut init: Func, | |
| 337 | + len: usize, | |
| 338 | + flags: Flags, | |
| 339 | + ) -> Result<Pin<Box<[T], A>>, E> | |
| 340 | + where | |
| 341 | + Func: FnMut(usize) -> Item, | |
| 342 | + Item: PinInit<T, E>, | |
| 343 | + E: From<AllocError>, | |
| 344 | + { | |
| 345 | + let mut buffer = super::Vec::<T, A>::with_capacity(len, flags)?; | |
| 346 | + for i in 0..len { | |
| 347 | + let ptr = buffer.spare_capacity_mut().as_mut_ptr().cast(); | |
| 348 | + // SAFETY: | |
| 349 | + // - `ptr` is a valid pointer to uninitialized memory. | |
| 350 | + // - `ptr` is not used if an error is returned. | |
| 351 | + // - `ptr` won't be moved until it is dropped, i.e. it is pinned. | |
| 352 | + unsafe { init(i).__pinned_init(ptr)? }; | |
| 353 | + | |
| 354 | + // SAFETY: | |
| 355 | + // - `i + 1 <= len`, hence we don't exceed the capacity, due to the call to | |
| 356 | + // `with_capacity()` above. | |
| 357 | + // - The new value at index buffer.len() + 1 is the only element being added here, and | |
| 358 | + // it has been initialized above by `init(i).__pinned_init(ptr)`. | |
| 359 | + unsafe { buffer.inc_len(1) }; | |
| 360 | + } | |
| 361 | + | |
| 362 | + let (ptr, _, _) = buffer.into_raw_parts(); | |
| 363 | + let slice = core::ptr::slice_from_raw_parts_mut(ptr, len); | |
| 364 | + | |
| 365 | + // SAFETY: `slice` points to an allocation allocated with `A` (`buffer`) and holds a valid | |
| 366 | + // `[T]`. | |
| 367 | + Ok(Pin::from(unsafe { Box::from_raw(slice) })) | |
| 368 | + } | |
| 369 | + | |
| 293 | 370 | /// Convert a [`Box<T,A>`] to a [`Pin<Box<T,A>>`]. If `T` does not implement |
| 294 | 371 | /// [`Unpin`], then `x` will be pinned in memory and can't be moved. |
| 295 | 372 | pub fn into_pin(this: Self) -> Pin<Self> { |
| @@ -401,12 +478,17 @@ where · 105 unmodified lines | ||
| 401 | 478 | } |
| 402 | 479 | |
| 403 | 480 | // SAFETY: The pointer returned by `into_foreign` comes from a well aligned |
| 404 | −// pointer to `T`. | |
| 481 | +// pointer to `T` allocated by `A`. | |
| 405 | 482 | unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A> |
| 406 | 483 | where |
| 407 | 484 | A: Allocator, |
| 408 | 485 | { |
| 409 | − const FOREIGN_ALIGN: usize = core::mem::align_of::<T>(); | |
| 486 | + const FOREIGN_ALIGN: usize = if core::mem::align_of::<T>() < A::MIN_ALIGN { | |
| 487 | + A::MIN_ALIGN | |
| 488 | + } else { | |
| 489 | + core::mem::align_of::<T>() | |
| 490 | + }; | |
| 491 | + | |
| 410 | 492 | type Borrowed<'a> = &'a T; |
| 411 | 493 | type BorrowedMut<'a> = &'a mut T; |
| 412 | 494 | |
| @@ -435,12 +517,12 @@ where · 22 unmodified lines | ||
| 435 | 517 | } |
| 436 | 518 | |
| 437 | 519 | // SAFETY: The pointer returned by `into_foreign` comes from a well aligned |
| 438 | −// pointer to `T`. | |
| 520 | +// pointer to `T` allocated by `A`. | |
| 439 | 521 | unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>> |
| 440 | 522 | where |
| 441 | 523 | A: Allocator, |
| 442 | 524 | { |
| 443 | − const FOREIGN_ALIGN: usize = core::mem::align_of::<T>(); | |
| 525 | + const FOREIGN_ALIGN: usize = <Box<T, A> as ForeignOwnable>::FOREIGN_ALIGN; | |
| 444 | 526 | type Borrowed<'a> = Pin<&'a T>; |
| 445 | 527 | type BorrowedMut<'a> = Pin<&'a mut T>; |
| 446 | 528 | |
| @@ -7,9 +7,9 @@ use super::{ · 6 unmodified lines | ||
| 7 | 7 | layout::ArrayLayout, |
| 8 | 8 | AllocError, Allocator, Box, Flags, |
| 9 | 9 | }; |
| 10 | +use crate::fmt; | |
| 10 | 11 | use core::{ |
| 11 | 12 | borrow::{Borrow, BorrowMut}, |
| 12 | − fmt, | |
| 13 | 13 | marker::PhantomData, |
| 14 | 14 | mem::{ManuallyDrop, MaybeUninit}, |
| 15 | 15 | ops::Deref, |
| @@ -175,7 +175,7 @@ where · 159 unmodified lines | ||
| 175 | 175 | |
| 176 | 176 | /// Returns the number of elements that can be stored within the vector without allocating |
| 177 | 177 | /// additional memory. |
| 178 | − pub fn capacity(&self) -> usize { | |
| 178 | + pub const fn capacity(&self) -> usize { | |
| 179 | 179 | if const { Self::is_zst() } { |
| 180 | 180 | usize::MAX |
| 181 | 181 | } else { |
| @@ -185,7 +185,7 @@ where · 3 unmodified lines | ||
| 185 | 185 | |
| 186 | 186 | /// Returns the number of elements stored within the vector. |
| 187 | 187 | #[inline] |
| 188 | − pub fn len(&self) -> usize { | |
| 188 | + pub const fn len(&self) -> usize { | |
| 189 | 189 | self.len |
| 190 | 190 | } |
| 191 | 191 | |
| @@ -196,7 +196,7 @@ where · 4 unmodified lines | ||
| 196 | 196 | /// - `additional` must be less than or equal to `self.capacity - self.len`. |
| 197 | 197 | /// - All elements within the interval [`self.len`,`self.len + additional`) must be initialized. |
| 198 | 198 | #[inline] |
| 199 | − pub unsafe fn inc_len(&mut self, additional: usize) { | |
| 199 | + pub const unsafe fn inc_len(&mut self, additional: usize) { | |
| 200 | 200 | // Guaranteed by the type invariant to never underflow. |
| 201 | 201 | debug_assert!(additional <= self.capacity() - self.len()); |
| 202 | 202 | // INVARIANT: By the safety requirements of this method this represents the exact number of |
| @@ -224,6 +224,16 @@ where · 21 unmodified lines | ||
| 224 | 224 | } |
| 225 | 225 | |
| 226 | 226 | /// Returns a slice of the entire vector. |
| 227 | + /// | |
| 228 | + /// # Examples | |
| 229 | + /// | |
| 230 | + /// ``` | |
| 231 | + /// let mut v = KVec::new(); | |
| 232 | + /// v.push(1, GFP_KERNEL)?; | |
| 233 | + /// v.push(2, GFP_KERNEL)?; | |
| 234 | + /// assert_eq!(v.as_slice(), &[1, 2]); | |
| 235 | + /// # Ok::<(), Error>(()) | |
| 236 | + /// ``` | |
| 227 | 237 | #[inline] |
| 228 | 238 | pub fn as_slice(&self) -> &[T] { |
| 229 | 239 | self |
| @@ -245,7 +255,7 @@ where · 15 unmodified lines | ||
| 245 | 255 | /// Returns a raw pointer to the vector's backing buffer, or, if `T` is a ZST, a dangling raw |
| 246 | 256 | /// pointer. |
| 247 | 257 | #[inline] |
| 248 | − pub fn as_ptr(&self) -> *const T { | |
| 258 | + pub const fn as_ptr(&self) -> *const T { | |
| 249 | 259 | self.ptr.as_ptr() |
| 250 | 260 | } |
| 251 | 261 | |
| @@ -261,7 +271,7 @@ where · 9 unmodified lines | ||
| 261 | 271 | /// assert!(!v.is_empty()); |
| 262 | 272 | /// ``` |
| 263 | 273 | #[inline] |
| 264 | − pub fn is_empty(&self) -> bool { | |
| 274 | + pub const fn is_empty(&self) -> bool { | |
| 265 | 275 | self.len() == 0 |
| 266 | 276 | } |
| 267 | 277 | |
| @@ -1294,7 +1304,7 @@ impl<'vec, T> Drop for DrainAll<'vec, T> { · 1026 unmodified lines | ||
| 1294 | 1304 | } |
| 1295 | 1305 | } |
| 1296 | 1306 | |
| 1297 | −#[macros::kunit_tests(rust_kvec_kunit)] | |
| 1307 | +#[macros::kunit_tests(rust_kvec)] | |
| 1298 | 1308 | mod tests { |
| 1299 | 1309 | use super::*; |
| 1300 | 1310 | use crate::prelude::*; |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | //! Errors for the [`Vec`] type. |
| 4 | 4 | |
| 5 | −use core::fmt::{self, Debug, Formatter}; | |
| 5 | +use kernel::fmt::{self, Debug, Formatter}; | |
| 6 | 6 | use kernel::prelude::*; |
| 7 | 7 | |
| 8 | 8 | /// Error type for [`Vec::push_within_capacity`]. |
| @@ -80,7 +80,7 @@ impl<T> ArrayLayout<T> { · 79 unmodified lines | ||
| 80 | 80 | /// # Safety |
| 81 | 81 | /// |
| 82 | 82 | /// `len` must be a value, for which `len * size_of::<T>() <= isize::MAX` is true. |
| 83 | − pub unsafe fn new_unchecked(len: usize) -> Self { | |
| 83 | + pub const unsafe fn new_unchecked(len: usize) -> Self { | |
| 84 | 84 | // INVARIANT: By the safety requirements of this function |
| 85 | 85 | // `len * size_of::<T>() <= isize::MAX`. |
| 86 | 86 | Self { |
| @@ -105,8 +105,8 @@ pub struct DeviceId(bindings::auxiliary_device_id); · 104 unmodified lines | ||
| 105 | 105 | impl DeviceId { |
| 106 | 106 | /// Create a new [`DeviceId`] from name. |
| 107 | 107 | pub const fn new(modname: &'static CStr, name: &'static CStr) -> Self { |
| 108 | − let name = name.as_bytes_with_nul(); | |
| 109 | − let modname = modname.as_bytes_with_nul(); | |
| 108 | + let name = name.to_bytes_with_nul(); | |
| 109 | + let modname = modname.to_bytes_with_nul(); | |
| 110 | 110 | |
| 111 | 111 | // TODO: Replace with `bindings::auxiliary_device_id::default()` once stabilized for |
| 112 | 112 | // `const`. |
| @@ -82,7 +82,7 @@ · 81 unmodified lines | ||
| 82 | 82 | //! Arc::pin_init(TagSet::new(1, 256, 1), flags::GFP_KERNEL)?; |
| 83 | 83 | //! let mut disk = gen_disk::GenDiskBuilder::new() |
| 84 | 84 | //! .capacity_sectors(4096) |
| 85 | −//! .build(format_args!("myblk"), tagset)?; | |
| 85 | +//! .build(fmt!("myblk"), tagset)?; | |
| 86 | 86 | //! |
| 87 | 87 | //! # Ok::<(), kernel::error::Error>(()) |
| 88 | 88 | //! ``` |
| @@ -3,12 +3,12 @@ · 2 unmodified lines | ||
| 3 | 3 | //! Generic disk abstraction. |
| 4 | 4 | //! |
| 5 | 5 | //! C header: [`include/linux/blkdev.h`](srctree/include/linux/blkdev.h) |
| 6 | −//! C header: [`include/linux/blk_mq.h`](srctree/include/linux/blk_mq.h) | |
| 6 | +//! C header: [`include/linux/blk-mq.h`](srctree/include/linux/blk-mq.h) | |
| 7 | 7 | |
| 8 | 8 | use crate::block::mq::{raw_writer::RawWriter, Operations, TagSet}; |
| 9 | +use crate::fmt::{self, Write}; | |
| 9 | 10 | use crate::{bindings, error::from_err_ptr, error::Result, sync::Arc}; |
| 10 | 11 | use crate::{error, static_lock_class}; |
| 11 | −use core::fmt::{self, Write}; | |
| 12 | 12 | |
| 13 | 13 | /// A builder for [`GenDisk`]. |
| 14 | 14 | /// |
| @@ -1,8 +1,7 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | |
| 3 | −use core::fmt::{self, Write}; | |
| 4 | − | |
| 5 | 3 | use crate::error::Result; |
| 4 | +use crate::fmt::{self, Write}; | |
| 6 | 5 | use crate::prelude::EINVAL; |
| 7 | 6 | |
| 8 | 7 | /// A mutable reference to a byte buffer where a string can be written into. |
| @@ -263,7 +263,7 @@ impl<Data> Group<Data> { · 262 unmodified lines | ||
| 263 | 263 | try_pin_init!(Self { |
| 264 | 264 | group <- pin_init::init_zeroed().chain(|v: &mut Opaque<bindings::config_group>| { |
| 265 | 265 | let place = v.get(); |
| 266 | − let name = name.as_bytes_with_nul().as_ptr(); | |
| 266 | + let name = name.to_bytes_with_nul().as_ptr(); | |
| 267 | 267 | // SAFETY: It is safe to initialize a group once it has been zeroed. |
| 268 | 268 | unsafe { |
| 269 | 269 | bindings::config_group_init_type_name(place, name.cast(), item_type.as_ptr()) |
| @@ -613,7 +613,7 @@ where · 343 unmodified lines | ||
| 613 | 613 | pub const fn new(name: &'static CStr) -> Self { |
| 614 | 614 | Self { |
| 615 | 615 | attribute: Opaque::new(bindings::configfs_attribute { |
| 616 | − ca_name: name.as_char_ptr(), | |
| 616 | + ca_name: crate::str::as_char_ptr_in_const_context(name), | |
| 617 | 617 | ca_owner: core::ptr::null_mut(), |
| 618 | 618 | ca_mode: 0o660, |
| 619 | 619 | show: Some(Self::show), |
| @@ -109,6 +109,7 @@ impl CpuId { · 108 unmodified lines | ||
| 109 | 109 | /// unexpectedly due to preemption or CPU migration. It should only be |
| 110 | 110 | /// used when the context ensures that the task remains on the same CPU |
| 111 | 111 | /// or the users could use a stale (yet valid) CPU ID. |
| 112 | + #[inline] | |
| 112 | 113 | pub fn current() -> Self { |
| 113 | 114 | // SAFETY: raw_smp_processor_id() always returns a valid CPU ID. |
| 114 | 115 | unsafe { Self::from_u32_unchecked(bindings::raw_smp_processor_id()) } |
| @@ -27,7 +27,6 @@ use crate::clk::Clk; · 26 unmodified lines | ||
| 27 | 27 | use core::{ |
| 28 | 28 | cell::UnsafeCell, |
| 29 | 29 | marker::PhantomData, |
| 30 | − mem::MaybeUninit, | |
| 31 | 30 | ops::{Deref, DerefMut}, |
| 32 | 31 | pin::Pin, |
| 33 | 32 | ptr, |
| @@ -1013,12 +1012,11 @@ impl<T: Driver> Registration<T> { · 979 unmodified lines | ||
| 1013 | 1012 | } else { |
| 1014 | 1013 | None |
| 1015 | 1014 | }, |
| 1016 | − // SAFETY: All zeros is a valid value for `bindings::cpufreq_driver`. | |
| 1017 | − ..unsafe { MaybeUninit::zeroed().assume_init() } | |
| 1015 | + ..pin_init::zeroed() | |
| 1018 | 1016 | }; |
| 1019 | 1017 | |
| 1020 | 1018 | const fn copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN] { |
| 1021 | − let src = name.as_bytes_with_nul(); | |
| 1019 | + let src = name.to_bytes_with_nul(); | |
| 1022 | 1020 | let mut dst = [0; CPUFREQ_NAME_LEN]; |
| 1023 | 1021 | |
| 1024 | 1022 | build_assert!(src.len() <= CPUFREQ_NAME_LEN); |
| @@ -5,10 +5,10 @@ · 4 unmodified lines | ||
| 5 | 5 | //! C header: [`include/linux/device.h`](srctree/include/linux/device.h) |
| 6 | 6 | |
| 7 | 7 | use crate::{ |
| 8 | − bindings, | |
| 8 | + bindings, fmt, | |
| 9 | 9 | types::{ARef, ForeignOwnable, Opaque}, |
| 10 | 10 | }; |
| 11 | −use core::{fmt, marker::PhantomData, ptr}; | |
| 11 | +use core::{marker::PhantomData, ptr}; | |
| 12 | 12 | |
| 13 | 13 | #[cfg(CONFIG_PRINTK)] |
| 14 | 14 | use crate::c_str; |
| @@ -596,7 +596,7 @@ macro_rules! impl_device_context_into_aref { · 581 unmodified lines | ||
| 596 | 596 | macro_rules! dev_printk { |
| 597 | 597 | ($method:ident, $dev:expr, $($f:tt)*) => { |
| 598 | 598 | { |
| 599 | − ($dev).$method(::core::format_args!($($f)*)); | |
| 599 | + ($dev).$method($crate::prelude::fmt!($($f)*)); | |
| 600 | 600 | } |
| 601 | 601 | } |
| 602 | 602 | } |
| @@ -11,6 +11,7 @@ use crate::{ · 10 unmodified lines | ||
| 11 | 11 | alloc::KVec, |
| 12 | 12 | bindings, |
| 13 | 13 | error::{to_result, Result}, |
| 14 | + fmt, | |
| 14 | 15 | prelude::*, |
| 15 | 16 | str::{CStr, CString}, |
| 16 | 17 | types::{ARef, Opaque}, |
| @@ -68,16 +69,16 @@ impl FwNode { · 51 unmodified lines | ||
| 68 | 69 | unsafe { bindings::is_of_node(self.as_raw()) } |
| 69 | 70 | } |
| 70 | 71 | |
| 71 | − /// Returns an object that implements [`Display`](core::fmt::Display) for | |
| 72 | + /// Returns an object that implements [`Display`](fmt::Display) for | |
| 72 | 73 | /// printing the name of a node. |
| 73 | 74 | /// |
| 74 | 75 | /// This is an alternative to the default `Display` implementation, which |
| 75 | 76 | /// prints the full path. |
| 76 | − pub fn display_name(&self) -> impl core::fmt::Display + '_ { | |
| 77 | + pub fn display_name(&self) -> impl fmt::Display + '_ { | |
| 77 | 78 | struct FwNodeDisplayName<'a>(&'a FwNode); |
| 78 | 79 | |
| 79 | − impl core::fmt::Display for FwNodeDisplayName<'_> { | |
| 80 | − fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | |
| 80 | + impl fmt::Display for FwNodeDisplayName<'_> { | |
| 81 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| 81 | 82 | // SAFETY: `self` is valid by its type invariant. |
| 82 | 83 | let name = unsafe { bindings::fwnode_get_name(self.0.as_raw()) }; |
| 83 | 84 | if name.is_null() { |
| @@ -87,7 +88,7 @@ impl FwNode { · 3 unmodified lines | ||
| 87 | 88 | // - `fwnode_get_name` returns null or a valid C string. |
| 88 | 89 | // - `name` was checked to be non-null. |
| 89 | 90 | let name = unsafe { CStr::from_char_ptr(name) }; |
| 90 | − write!(f, "{name}") | |
| 91 | + fmt::Display::fmt(name, f) | |
| 91 | 92 | } |
| 92 | 93 | } |
| 93 | 94 | |
| @@ -351,8 +352,8 @@ impl FwNodeReferenceArgs { · 257 unmodified lines | ||
| 351 | 352 | } |
| 352 | 353 | } |
| 353 | 354 | |
| 354 | −impl core::fmt::Debug for FwNodeReferenceArgs { | |
| 355 | − fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | |
| 355 | +impl fmt::Debug for FwNodeReferenceArgs { | |
| 356 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| 356 | 357 | write!(f, "{:?}", self.as_slice()) |
| 357 | 358 | } |
| 358 | 359 | } |
| @@ -377,8 +378,8 @@ enum Node<'a> { · 18 unmodified lines | ||
| 377 | 378 | Owned(ARef<FwNode>), |
| 378 | 379 | } |
| 379 | 380 | |
| 380 | −impl core::fmt::Display for FwNode { | |
| 381 | − fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | |
| 381 | +impl fmt::Display for FwNode { | |
| 382 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| 382 | 383 | // The logic here is the same as the one in lib/vsprintf.c |
| 383 | 384 | // (fwnode_full_name_string). |
| 384 | 385 | |
| @@ -413,9 +414,9 @@ impl core::fmt::Display for FwNode { · 28 unmodified lines | ||
| 413 | 414 | // SAFETY: `fwnode_get_name_prefix` returns null or a |
| 414 | 415 | // valid C string. |
| 415 | 416 | let prefix = unsafe { CStr::from_char_ptr(prefix) }; |
| 416 | − write!(f, "{prefix}")?; | |
| 417 | + fmt::Display::fmt(prefix, f)?; | |
| 417 | 418 | } |
| 418 | − write!(f, "{}", fwnode.display_name())?; | |
| 419 | + fmt::Display::fmt(&fwnode.display_name(), f)?; | |
| 419 | 420 | } |
| 420 | 421 | |
| 421 | 422 | Ok(()) |
| @@ -9,8 +9,8 @@ use crate::{ · 8 unmodified lines | ||
| 9 | 9 | device::{Bound, Core}, |
| 10 | 10 | error::{to_result, Result}, |
| 11 | 11 | prelude::*, |
| 12 | + sync::aref::ARef, | |
| 12 | 13 | transmute::{AsBytes, FromBytes}, |
| 13 | − types::ARef, | |
| 14 | 14 | }; |
| 15 | 15 | |
| 16 | 16 | /// Trait to be implemented by DMA capable bus devices. |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | //! DRM device. |
| 4 | 4 | //! |
| 5 | −//! C header: [`include/linux/drm/drm_device.h`](srctree/include/linux/drm/drm_device.h) | |
| 5 | +//! C header: [`include/drm/drm_device.h`](srctree/include/drm/drm_device.h) | |
| 6 | 6 | |
| 7 | 7 | use crate::{ |
| 8 | 8 | alloc::allocator::Kmalloc, |
| @@ -82,8 +82,8 @@ impl<T: drm::Driver> Device<T> { · 73 unmodified lines | ||
| 82 | 82 | major: T::INFO.major, |
| 83 | 83 | minor: T::INFO.minor, |
| 84 | 84 | patchlevel: T::INFO.patchlevel, |
| 85 | − name: T::INFO.name.as_char_ptr().cast_mut(), | |
| 86 | − desc: T::INFO.desc.as_char_ptr().cast_mut(), | |
| 85 | + name: crate::str::as_char_ptr_in_const_context(T::INFO.name).cast_mut(), | |
| 86 | + desc: crate::str::as_char_ptr_in_const_context(T::INFO.desc).cast_mut(), | |
| 87 | 87 | |
| 88 | 88 | driver_features: drm::driver::FEAT_GEM, |
| 89 | 89 | ioctls: T::IOCTLS.as_ptr(), |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | //! DRM driver core. |
| 4 | 4 | //! |
| 5 | −//! C header: [`include/linux/drm/drm_drv.h`](srctree/include/linux/drm/drm_drv.h) | |
| 5 | +//! C header: [`include/drm/drm_drv.h`](srctree/include/drm/drm_drv.h) | |
| 6 | 6 | |
| 7 | 7 | use crate::{ |
| 8 | 8 | bindings, device, devres, drm, |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | //! DRM File objects. |
| 4 | 4 | //! |
| 5 | −//! C header: [`include/linux/drm/drm_file.h`](srctree/include/linux/drm/drm_file.h) | |
| 5 | +//! C header: [`include/drm/drm_file.h`](srctree/include/drm/drm_file.h) | |
| 6 | 6 | |
| 7 | 7 | use crate::{bindings, drm, error::Result, prelude::*, types::Opaque}; |
| 8 | 8 | use core::marker::PhantomData; |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | //! DRM GEM API |
| 4 | 4 | //! |
| 5 | −//! C header: [`include/linux/drm/drm_gem.h`](srctree/include/linux/drm/drm_gem.h) | |
| 5 | +//! C header: [`include/drm/drm_gem.h`](srctree/include/drm/drm_gem.h) | |
| 6 | 6 | |
| 7 | 7 | use crate::{ |
| 8 | 8 | alloc::flags::*, |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | //! DRM IOCTL definitions. |
| 4 | 4 | //! |
| 5 | −//! C header: [`include/linux/drm/drm_ioctl.h`](srctree/include/linux/drm/drm_ioctl.h) | |
| 5 | +//! C header: [`include/drm/drm_ioctl.h`](srctree/include/drm/drm_ioctl.h) | |
| 6 | 6 | |
| 7 | 7 | use crate::ioctl; |
| 8 | 8 | |
| @@ -2,7 +2,9 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | //! Kernel errors. |
| 4 | 4 | //! |
| 5 | −//! C header: [`include/uapi/asm-generic/errno-base.h`](srctree/include/uapi/asm-generic/errno-base.h) | |
| 5 | +//! C header: [`include/uapi/asm-generic/errno-base.h`](srctree/include/uapi/asm-generic/errno-base.h)\ | |
| 6 | +//! C header: [`include/uapi/asm-generic/errno.h`](srctree/include/uapi/asm-generic/errno.h)\ | |
| 7 | +//! C header: [`include/linux/errno.h`](srctree/include/linux/errno.h) | |
| 6 | 8 | |
| 7 | 9 | use crate::{ |
| 8 | 10 | alloc::{layout::LayoutError, AllocError}, |
| @@ -101,8 +103,23 @@ pub struct Error(NonZeroI32); · 92 unmodified lines | ||
| 101 | 103 | impl Error { |
| 102 | 104 | /// Creates an [`Error`] from a kernel error code. |
| 103 | 105 | /// |
| 104 | − /// It is a bug to pass an out-of-range `errno`. `EINVAL` would | |
| 105 | − /// be returned in such a case. | |
| 106 | + /// `errno` must be within error code range (i.e. `>= -MAX_ERRNO && < 0`). | |
| 107 | + /// | |
| 108 | + /// It is a bug to pass an out-of-range `errno`. [`code::EINVAL`] is returned in such a case. | |
| 109 | + /// | |
| 110 | + /// # Examples | |
| 111 | + /// | |
| 112 | + /// ``` | |
| 113 | + /// assert_eq!(Error::from_errno(-1), EPERM); | |
| 114 | + /// assert_eq!(Error::from_errno(-2), ENOENT); | |
| 115 | + /// ``` | |
| 116 | + /// | |
| 117 | + /// The following calls are considered a bug: | |
| 118 | + /// | |
| 119 | + /// ``` | |
| 120 | + /// assert_eq!(Error::from_errno(0), EINVAL); | |
| 121 | + /// assert_eq!(Error::from_errno(-1000000), EINVAL); | |
| 122 | + /// ``` | |
| 106 | 123 | pub fn from_errno(errno: crate::ffi::c_int) -> Error { |
| 107 | 124 | if let Some(error) = Self::try_from_errno(errno) { |
| 108 | 125 | error |
| @@ -158,7 +175,7 @@ impl Error { · 49 unmodified lines | ||
| 158 | 175 | } |
| 159 | 176 | |
| 160 | 177 | /// Returns a string representing the error, if one exists. |
| 161 | − #[cfg(not(any(test, testlib)))] | |
| 178 | + #[cfg(not(testlib))] | |
| 162 | 179 | pub fn name(&self) -> Option<&'static CStr> { |
| 163 | 180 | // SAFETY: Just an FFI call, there are no extra safety requirements. |
| 164 | 181 | let ptr = unsafe { bindings::errname(-self.0.get()) }; |
| @@ -175,7 +192,7 @@ impl Error { · 10 unmodified lines | ||
| 175 | 192 | /// When `testlib` is configured, this always returns `None` to avoid the dependency on a |
| 176 | 193 | /// kernel function so that tests that use this (e.g., by calling [`Result::unwrap`]) can still |
| 177 | 194 | /// run in userspace. |
| 178 | − #[cfg(any(test, testlib))] | |
| 195 | + #[cfg(testlib)] | |
| 179 | 196 | pub fn name(&self) -> Option<&'static CStr> { |
| 180 | 197 | None |
| 181 | 198 | } |
| @@ -375,8 +392,43 @@ impl From<core::convert::Infallible> for Error { · 193 unmodified lines | ||
| 375 | 392 | /// [Rust documentation]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html |
| 376 | 393 | pub type Result<T = (), E = Error> = core::result::Result<T, E>; |
| 377 | 394 | |
| 378 | −/// Converts an integer as returned by a C kernel function to an error if it's negative, and | |
| 379 | −/// `Ok(())` otherwise. | |
| 395 | +/// Converts an integer as returned by a C kernel function to a [`Result`]. | |
| 396 | +/// | |
| 397 | +/// If the integer is negative, an [`Err`] with an [`Error`] as given by [`Error::from_errno`] is | |
| 398 | +/// returned. This means the integer must be `>= -MAX_ERRNO`. | |
| 399 | +/// | |
| 400 | +/// Otherwise, it returns [`Ok`]. | |
| 401 | +/// | |
| 402 | +/// It is a bug to pass an out-of-range negative integer. `Err(EINVAL)` is returned in such a case. | |
| 403 | +/// | |
| 404 | +/// # Examples | |
| 405 | +/// | |
| 406 | +/// This function may be used to easily perform early returns with the [`?`] operator when working | |
| 407 | +/// with C APIs within Rust abstractions: | |
| 408 | +/// | |
| 409 | +/// ``` | |
| 410 | +/// # use kernel::error::to_result; | |
| 411 | +/// # mod bindings { | |
| 412 | +/// # #![expect(clippy::missing_safety_doc)] | |
| 413 | +/// # use kernel::prelude::*; | |
| 414 | +/// # pub(super) unsafe fn f1() -> c_int { 0 } | |
| 415 | +/// # pub(super) unsafe fn f2() -> c_int { EINVAL.to_errno() } | |
| 416 | +/// # } | |
| 417 | +/// fn f() -> Result { | |
| 418 | +/// // SAFETY: ... | |
| 419 | +/// to_result(unsafe { bindings::f1() })?; | |
| 420 | +/// | |
| 421 | +/// // SAFETY: ... | |
| 422 | +/// to_result(unsafe { bindings::f2() })?; | |
| 423 | +/// | |
| 424 | +/// // ... | |
| 425 | +/// | |
| 426 | +/// Ok(()) | |
| 427 | +/// } | |
| 428 | +/// # assert_eq!(f(), Err(EINVAL)); | |
| 429 | +/// ``` | |
| 430 | +/// | |
| 431 | +/// [`?`]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator | |
| 380 | 432 | pub fn to_result(err: crate::ffi::c_int) -> Result { |
| 381 | 433 | if err < 0 { |
| 382 | 434 | Err(Error::from_errno(err)) |
| @@ -291,7 +291,7 @@ impl<const N: usize> ModInfoBuilder<N> { · 290 unmodified lines | ||
| 291 | 291 | let module_name = this.module_name; |
| 292 | 292 | |
| 293 | 293 | if !this.module_name.is_empty() { |
| 294 | − this = this.push_internal(module_name.as_bytes_with_nul()); | |
| 294 | + this = this.push_internal(module_name.to_bytes_with_nul()); | |
| 295 | 295 | |
| 296 | 296 | if N != 0 { |
| 297 | 297 | // Re-use the space taken by the NULL terminator and swap it with the '.' separator. |
| @@ -11,6 +11,7 @@ use crate::{ · 10 unmodified lines | ||
| 11 | 11 | bindings, |
| 12 | 12 | cred::Credential, |
| 13 | 13 | error::{code::*, to_result, Error, Result}, |
| 14 | + fmt, | |
| 14 | 15 | sync::aref::{ARef, AlwaysRefCounted}, |
| 15 | 16 | types::{NotThreadSafe, Opaque}, |
| 16 | 17 | }; |
| @@ -460,8 +461,8 @@ impl From<BadFdError> for Error { · 443 unmodified lines | ||
| 460 | 461 | } |
| 461 | 462 | } |
| 462 | 463 | |
| 463 | −impl core::fmt::Debug for BadFdError { | |
| 464 | − fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | |
| 464 | +impl fmt::Debug for BadFdError { | |
| 465 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| 465 | 466 | f.pad("EBADF") |
| 466 | 467 | } |
| 467 | 468 | } |
| @@ -6,8 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | //! |
| 7 | 7 | //! Reference: <https://docs.kernel.org/dev-tools/kunit/index.html> |
| 8 | 8 | |
| 9 | +use crate::fmt; | |
| 9 | 10 | use crate::prelude::*; |
| 10 | −use core::fmt; | |
| 11 | 11 | |
| 12 | 12 | #[cfg(CONFIG_PRINTK)] |
| 13 | 13 | use crate::c_str; |
| @@ -74,14 +74,14 @@ macro_rules! kunit_assert { · 60 unmodified lines | ||
| 74 | 74 | // mistake (it is hidden to prevent that). |
| 75 | 75 | // |
| 76 | 76 | // This mimics KUnit's failed assertion format. |
| 77 | − $crate::kunit::err(format_args!( | |
| 77 | + $crate::kunit::err($crate::prelude::fmt!( | |
| 78 | 78 | " # {}: ASSERTION FAILED at {FILE}:{LINE}\n", |
| 79 | 79 | $name |
| 80 | 80 | )); |
| 81 | − $crate::kunit::err(format_args!( | |
| 81 | + $crate::kunit::err($crate::prelude::fmt!( | |
| 82 | 82 | " Expected {CONDITION} to be true, but is false\n" |
| 83 | 83 | )); |
| 84 | − $crate::kunit::err(format_args!( | |
| 84 | + $crate::kunit::err($crate::prelude::fmt!( | |
| 85 | 85 | " Failure not reported to KUnit since this is a non-KUnit task\n" |
| 86 | 86 | )); |
| 87 | 87 | break 'out; |
| @@ -102,12 +102,12 @@ macro_rules! kunit_assert { · 14 unmodified lines | ||
| 102 | 102 | unsafe impl Sync for UnaryAssert {} |
| 103 | 103 | |
| 104 | 104 | static LOCATION: Location = Location($crate::bindings::kunit_loc { |
| 105 | − file: FILE.as_char_ptr(), | |
| 105 | + file: $crate::str::as_char_ptr_in_const_context(FILE), | |
| 106 | 106 | line: LINE, |
| 107 | 107 | }); |
| 108 | 108 | static ASSERTION: UnaryAssert = UnaryAssert($crate::bindings::kunit_unary_assert { |
| 109 | 109 | assert: $crate::bindings::kunit_assert {}, |
| 110 | − condition: CONDITION.as_char_ptr(), | |
| 110 | + condition: $crate::str::as_char_ptr_in_const_context(CONDITION), | |
| 111 | 111 | expected_true: true, |
| 112 | 112 | }); |
| 113 | 113 | |
| @@ -202,7 +202,7 @@ pub const fn kunit_case( · 88 unmodified lines | ||
| 202 | 202 | ) -> kernel::bindings::kunit_case { |
| 203 | 203 | kernel::bindings::kunit_case { |
| 204 | 204 | run_case: Some(run_case), |
| 205 | − name: name.as_char_ptr(), | |
| 205 | + name: kernel::str::as_char_ptr_in_const_context(name), | |
| 206 | 206 | attr: kernel::bindings::kunit_attributes { |
| 207 | 207 | speed: kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL, |
| 208 | 208 | }, |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | // the unstable features in use. |
| 18 | 18 | // |
| 19 | 19 | // Stable since Rust 1.79.0. |
| 20 | +#![feature(generic_nonzero)] | |
| 20 | 21 | #![feature(inline_const)] |
| 21 | 22 | // |
| 22 | 23 | // Stable since Rust 1.81.0. |
| @@ -28,6 +29,7 @@ · 5 unmodified lines | ||
| 28 | 29 | // Stable since Rust 1.83.0. |
| 29 | 30 | #![feature(const_maybe_uninit_as_mut_ptr)] |
| 30 | 31 | #![feature(const_mut_refs)] |
| 32 | +#![feature(const_option)] | |
| 31 | 33 | #![feature(const_ptr_write)] |
| 32 | 34 | #![feature(const_refs_to_cell)] |
| 33 | 35 | // |
| @@ -110,6 +112,7 @@ pub mod pid_namespace; · 76 unmodified lines | ||
| 110 | 112 | pub mod platform; |
| 111 | 113 | pub mod prelude; |
| 112 | 114 | pub mod print; |
| 115 | +pub mod ptr; | |
| 113 | 116 | pub mod rbtree; |
| 114 | 117 | pub mod regulator; |
| 115 | 118 | pub mod revocable; |
| @@ -206,7 +209,7 @@ impl ThisModule { · 90 unmodified lines | ||
| 206 | 209 | } |
| 207 | 210 | } |
| 208 | 211 | |
| 209 | −#[cfg(not(any(testlib, test)))] | |
| 212 | +#[cfg(not(testlib))] | |
| 210 | 213 | #[panic_handler] |
| 211 | 214 | fn panic(info: &core::panic::PanicInfo<'_>) -> ! { |
| 212 | 215 | pr_emerg!("{}\n", info); |
| @@ -38,6 +38,8 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField}; · 37 unmodified lines | ||
| 38 | 38 | /// |
| 39 | 39 | /// # Examples |
| 40 | 40 | /// |
| 41 | +/// Use [`ListLinks`] as the type of the intrusive field. | |
| 42 | +/// | |
| 41 | 43 | /// ``` |
| 42 | 44 | /// use kernel::list::*; |
| 43 | 45 | /// |
| @@ -140,6 +142,124 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField}; · 96 unmodified lines | ||
| 140 | 142 | /// } |
| 141 | 143 | /// # Result::<(), Error>::Ok(()) |
| 142 | 144 | /// ``` |
| 145 | +/// | |
| 146 | +/// Use [`ListLinksSelfPtr`] as the type of the intrusive field. This allows a list of trait object | |
| 147 | +/// type. | |
| 148 | +/// | |
| 149 | +/// ``` | |
| 150 | +/// use kernel::list::*; | |
| 151 | +/// | |
| 152 | +/// trait Foo { | |
| 153 | +/// fn foo(&self) -> (&'static str, i32); | |
| 154 | +/// } | |
| 155 | +/// | |
| 156 | +/// #[pin_data] | |
| 157 | +/// struct DTWrap<T: ?Sized> { | |
| 158 | +/// #[pin] | |
| 159 | +/// links: ListLinksSelfPtr<DTWrap<dyn Foo>>, | |
| 160 | +/// value: T, | |
| 161 | +/// } | |
| 162 | +/// | |
| 163 | +/// impl<T> DTWrap<T> { | |
| 164 | +/// fn new(value: T) -> Result<ListArc<Self>> { | |
| 165 | +/// ListArc::pin_init(try_pin_init!(Self { | |
| 166 | +/// value, | |
| 167 | +/// links <- ListLinksSelfPtr::new(), | |
| 168 | +/// }), GFP_KERNEL) | |
| 169 | +/// } | |
| 170 | +/// } | |
| 171 | +/// | |
| 172 | +/// impl_list_arc_safe! { | |
| 173 | +/// impl{T: ?Sized} ListArcSafe<0> for DTWrap<T> { untracked; } | |
| 174 | +/// } | |
| 175 | +/// impl_list_item! { | |
| 176 | +/// impl ListItem<0> for DTWrap<dyn Foo> { using ListLinksSelfPtr { self.links }; } | |
| 177 | +/// } | |
| 178 | +/// | |
| 179 | +/// // Create a new empty list. | |
| 180 | +/// let mut list = List::<DTWrap<dyn Foo>>::new(); | |
| 181 | +/// { | |
| 182 | +/// assert!(list.is_empty()); | |
| 183 | +/// } | |
| 184 | +/// | |
| 185 | +/// struct A(i32); | |
| 186 | +/// // `A` returns the inner value for `foo`. | |
| 187 | +/// impl Foo for A { fn foo(&self) -> (&'static str, i32) { ("a", self.0) } } | |
| 188 | +/// | |
| 189 | +/// struct B; | |
| 190 | +/// // `B` always returns 42. | |
| 191 | +/// impl Foo for B { fn foo(&self) -> (&'static str, i32) { ("b", 42) } } | |
| 192 | +/// | |
| 193 | +/// // Insert 3 element using `push_back()`. | |
| 194 | +/// list.push_back(DTWrap::new(A(15))?); | |
| 195 | +/// list.push_back(DTWrap::new(A(32))?); | |
| 196 | +/// list.push_back(DTWrap::new(B)?); | |
| 197 | +/// | |
| 198 | +/// // Iterate over the list to verify the nodes were inserted correctly. | |
| 199 | +/// // [A(15), A(32), B] | |
| 200 | +/// { | |
| 201 | +/// let mut iter = list.iter(); | |
| 202 | +/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 15)); | |
| 203 | +/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 32)); | |
| 204 | +/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42)); | |
| 205 | +/// assert!(iter.next().is_none()); | |
| 206 | +/// | |
| 207 | +/// // Verify the length of the list. | |
| 208 | +/// assert_eq!(list.iter().count(), 3); | |
| 209 | +/// } | |
| 210 | +/// | |
| 211 | +/// // Pop the items from the list using `pop_back()` and verify the content. | |
| 212 | +/// { | |
| 213 | +/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("b", 42)); | |
| 214 | +/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 32)); | |
| 215 | +/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 15)); | |
| 216 | +/// } | |
| 217 | +/// | |
| 218 | +/// // Insert 3 elements using `push_front()`. | |
| 219 | +/// list.push_front(DTWrap::new(A(15))?); | |
| 220 | +/// list.push_front(DTWrap::new(A(32))?); | |
| 221 | +/// list.push_front(DTWrap::new(B)?); | |
| 222 | +/// | |
| 223 | +/// // Iterate over the list to verify the nodes were inserted correctly. | |
| 224 | +/// // [B, A(32), A(15)] | |
| 225 | +/// { | |
| 226 | +/// let mut iter = list.iter(); | |
| 227 | +/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42)); | |
| 228 | +/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 32)); | |
| 229 | +/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 15)); | |
| 230 | +/// assert!(iter.next().is_none()); | |
| 231 | +/// | |
| 232 | +/// // Verify the length of the list. | |
| 233 | +/// assert_eq!(list.iter().count(), 3); | |
| 234 | +/// } | |
| 235 | +/// | |
| 236 | +/// // Pop the items from the list using `pop_front()` and verify the content. | |
| 237 | +/// { | |
| 238 | +/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 15)); | |
| 239 | +/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 32)); | |
| 240 | +/// } | |
| 241 | +/// | |
| 242 | +/// // Push `list2` to `list` through `push_all_back()`. | |
| 243 | +/// // list: [B] | |
| 244 | +/// // list2: [B, A(25)] | |
| 245 | +/// { | |
| 246 | +/// let mut list2 = List::<DTWrap<dyn Foo>>::new(); | |
| 247 | +/// list2.push_back(DTWrap::new(B)?); | |
| 248 | +/// list2.push_back(DTWrap::new(A(25))?); | |
| 249 | +/// | |
| 250 | +/// list.push_all_back(&mut list2); | |
| 251 | +/// | |
| 252 | +/// // list: [B, B, A(25)] | |
| 253 | +/// // list2: [] | |
| 254 | +/// let mut iter = list.iter(); | |
| 255 | +/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42)); | |
| 256 | +/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42)); | |
| 257 | +/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 25)); | |
| 258 | +/// assert!(iter.next().is_none()); | |
| 259 | +/// assert!(list2.is_empty()); | |
| 260 | +/// } | |
| 261 | +/// # Result::<(), Error>::Ok(()) | |
| 262 | +/// ``` | |
| 143 | 263 | pub struct List<T: ?Sized + ListItem<ID>, const ID: u64 = 0> { |
| 144 | 264 | first: *mut ListLinksFields, |
| 145 | 265 | _ty: PhantomData<ListArc<T, ID>>, |
| @@ -34,7 +34,7 @@ impl MiscDeviceOptions { · 33 unmodified lines | ||
| 34 | 34 | // SAFETY: All zeros is valid for this C type. |
| 35 | 35 | let mut result: bindings::miscdevice = unsafe { MaybeUninit::zeroed().assume_init() }; |
| 36 | 36 | result.minor = bindings::MISC_DYNAMIC_MINOR as ffi::c_int; |
| 37 | − result.name = self.name.as_char_ptr(); | |
| 37 | + result.name = crate::str::as_char_ptr_in_const_context(self.name); | |
| 38 | 38 | result.fops = MiscdeviceVTable::<T>::build(); |
| 39 | 39 | result |
| 40 | 40 | } |
| @@ -497,7 +497,7 @@ unsafe impl Sync for DriverVTable {} · 496 unmodified lines | ||
| 497 | 497 | pub const fn create_phy_driver<T: Driver>() -> DriverVTable { |
| 498 | 498 | // INVARIANT: All the fields of `struct phy_driver` are initialized properly. |
| 499 | 499 | DriverVTable(Opaque::new(bindings::phy_driver { |
| 500 | − name: T::NAME.as_char_ptr().cast_mut(), | |
| 500 | + name: crate::str::as_char_ptr_in_const_context(T::NAME).cast_mut(), | |
| 501 | 501 | flags: T::FLAGS, |
| 502 | 502 | phy_id: T::PHY_DEVICE_ID.id(), |
| 503 | 503 | phy_id_mask: T::PHY_DEVICE_ID.mask_as_int(), |
| @@ -34,7 +34,7 @@ unsafe impl RawDeviceIdIndex for DeviceId { · 33 unmodified lines | ||
| 34 | 34 | impl DeviceId { |
| 35 | 35 | /// Create a new device id from an OF 'compatible' string. |
| 36 | 36 | pub const fn new(compatible: &'static CStr) -> Self { |
| 37 | − let src = compatible.as_bytes_with_nul(); | |
| 37 | + let src = compatible.to_bytes_with_nul(); | |
| 38 | 38 | // Replace with `bindings::of_device_id::default()` once stabilized for `const`. |
| 39 | 39 | // SAFETY: FFI type is valid to be zero-initialized. |
| 40 | 40 | let mut of: bindings::of_device_id = unsafe { core::mem::zeroed() }; |
| @@ -12,7 +12,10 @@ · 11 unmodified lines | ||
| 12 | 12 | //! ``` |
| 13 | 13 | |
| 14 | 14 | #[doc(no_inline)] |
| 15 | −pub use core::pin::Pin; | |
| 15 | +pub use core::{ | |
| 16 | + mem::{align_of, align_of_val, size_of, size_of_val}, | |
| 17 | + pin::Pin, | |
| 18 | +}; | |
| 16 | 19 | |
| 17 | 20 | pub use ::ffi::{ |
| 18 | 21 | c_char, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong, c_ulonglong, |
| @@ -0,0 +1,228 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +//! Types and functions to work with pointers and addresses. | |
| 4 | + | |
| 5 | +use core::fmt::Debug; | |
| 6 | +use core::mem::align_of; | |
| 7 | +use core::num::NonZero; | |
| 8 | + | |
| 9 | +use crate::build_assert; | |
| 10 | + | |
| 11 | +/// Type representing an alignment, which is always a power of two. | |
| 12 | +/// | |
| 13 | +/// It is used to validate that a given value is a valid alignment, and to perform masking and | |
| 14 | +/// alignment operations. | |
| 15 | +/// | |
| 16 | +/// This is a temporary substitute for the [`Alignment`] nightly type from the standard library, | |
| 17 | +/// and to be eventually replaced by it. | |
| 18 | +/// | |
| 19 | +/// [`Alignment`]: https://github.com/rust-lang/rust/issues/102070 | |
| 20 | +/// | |
| 21 | +/// # Invariants | |
| 22 | +/// | |
| 23 | +/// An alignment is always a power of two. | |
| 24 | +#[repr(transparent)] | |
| 25 | +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | |
| 26 | +pub struct Alignment(NonZero<usize>); | |
| 27 | + | |
| 28 | +impl Alignment { | |
| 29 | + /// Validates that `ALIGN` is a power of two at build-time, and returns an [`Alignment`] of the | |
| 30 | + /// same value. | |
| 31 | + /// | |
| 32 | + /// A build error is triggered if `ALIGN` is not a power of two. | |
| 33 | + /// | |
| 34 | + /// # Examples | |
| 35 | + /// | |
| 36 | + /// ``` | |
| 37 | + /// use kernel::ptr::Alignment; | |
| 38 | + /// | |
| 39 | + /// let v = Alignment::new::<16>(); | |
| 40 | + /// assert_eq!(v.as_usize(), 16); | |
| 41 | + /// ``` | |
| 42 | + #[inline(always)] | |
| 43 | + pub const fn new<const ALIGN: usize>() -> Self { | |
| 44 | + build_assert!( | |
| 45 | + ALIGN.is_power_of_two(), | |
| 46 | + "Provided alignment is not a power of two." | |
| 47 | + ); | |
| 48 | + | |
| 49 | + // INVARIANT: `align` is a power of two. | |
| 50 | + // SAFETY: `align` is a power of two, and thus non-zero. | |
| 51 | + Self(unsafe { NonZero::new_unchecked(ALIGN) }) | |
| 52 | + } | |
| 53 | + | |
| 54 | + /// Validates that `align` is a power of two at runtime, and returns an | |
| 55 | + /// [`Alignment`] of the same value. | |
| 56 | + /// | |
| 57 | + /// Returns [`None`] if `align` is not a power of two. | |
| 58 | + /// | |
| 59 | + /// # Examples | |
| 60 | + /// | |
| 61 | + /// ``` | |
| 62 | + /// use kernel::ptr::Alignment; | |
| 63 | + /// | |
| 64 | + /// assert_eq!(Alignment::new_checked(16), Some(Alignment::new::<16>())); | |
| 65 | + /// assert_eq!(Alignment::new_checked(15), None); | |
| 66 | + /// assert_eq!(Alignment::new_checked(1), Some(Alignment::new::<1>())); | |
| 67 | + /// assert_eq!(Alignment::new_checked(0), None); | |
| 68 | + /// ``` | |
| 69 | + #[inline(always)] | |
| 70 | + pub const fn new_checked(align: usize) -> Option<Self> { | |
| 71 | + if align.is_power_of_two() { | |
| 72 | + // INVARIANT: `align` is a power of two. | |
| 73 | + // SAFETY: `align` is a power of two, and thus non-zero. | |
| 74 | + Some(Self(unsafe { NonZero::new_unchecked(align) })) | |
| 75 | + } else { | |
| 76 | + None | |
| 77 | + } | |
| 78 | + } | |
| 79 | + | |
| 80 | + /// Returns the alignment of `T`. | |
| 81 | + /// | |
| 82 | + /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`]. | |
| 83 | + #[inline(always)] | |
| 84 | + pub const fn of<T>() -> Self { | |
| 85 | + #![allow(clippy::incompatible_msrv)] | |
| 86 | + // This cannot panic since alignments are always powers of two. | |
| 87 | + // | |
| 88 | + // We unfortunately cannot use `new` as it would require the `generic_const_exprs` feature. | |
| 89 | + const { Alignment::new_checked(align_of::<T>()).unwrap() } | |
| 90 | + } | |
| 91 | + | |
| 92 | + /// Returns this alignment as a [`usize`]. | |
| 93 | + /// | |
| 94 | + /// It is guaranteed to be a power of two. | |
| 95 | + /// | |
| 96 | + /// # Examples | |
| 97 | + /// | |
| 98 | + /// ``` | |
| 99 | + /// use kernel::ptr::Alignment; | |
| 100 | + /// | |
| 101 | + /// assert_eq!(Alignment::new::<16>().as_usize(), 16); | |
| 102 | + /// ``` | |
| 103 | + #[inline(always)] | |
| 104 | + pub const fn as_usize(self) -> usize { | |
| 105 | + self.as_nonzero().get() | |
| 106 | + } | |
| 107 | + | |
| 108 | + /// Returns this alignment as a [`NonZero`]. | |
| 109 | + /// | |
| 110 | + /// It is guaranteed to be a power of two. | |
| 111 | + /// | |
| 112 | + /// # Examples | |
| 113 | + /// | |
| 114 | + /// ``` | |
| 115 | + /// use kernel::ptr::Alignment; | |
| 116 | + /// | |
| 117 | + /// assert_eq!(Alignment::new::<16>().as_nonzero().get(), 16); | |
| 118 | + /// ``` | |
| 119 | + #[inline(always)] | |
| 120 | + pub const fn as_nonzero(self) -> NonZero<usize> { | |
| 121 | + // Allow the compiler to know that the value is indeed a power of two. This can help | |
| 122 | + // optimize some operations down the line, like e.g. replacing divisions by bit shifts. | |
| 123 | + if !self.0.is_power_of_two() { | |
| 124 | + // SAFETY: Per the invariants, `self.0` is always a power of two so this block will | |
| 125 | + // never be reached. | |
| 126 | + unsafe { core::hint::unreachable_unchecked() } | |
| 127 | + } | |
| 128 | + self.0 | |
| 129 | + } | |
| 130 | + | |
| 131 | + /// Returns the base-2 logarithm of the alignment. | |
| 132 | + /// | |
| 133 | + /// # Examples | |
| 134 | + /// | |
| 135 | + /// ``` | |
| 136 | + /// use kernel::ptr::Alignment; | |
| 137 | + /// | |
| 138 | + /// assert_eq!(Alignment::of::<u8>().log2(), 0); | |
| 139 | + /// assert_eq!(Alignment::new::<16>().log2(), 4); | |
| 140 | + /// ``` | |
| 141 | + #[inline(always)] | |
| 142 | + pub const fn log2(self) -> u32 { | |
| 143 | + self.0.ilog2() | |
| 144 | + } | |
| 145 | + | |
| 146 | + /// Returns the mask for this alignment. | |
| 147 | + /// | |
| 148 | + /// This is equivalent to `!(self.as_usize() - 1)`. | |
| 149 | + /// | |
| 150 | + /// # Examples | |
| 151 | + /// | |
| 152 | + /// ``` | |
| 153 | + /// use kernel::ptr::Alignment; | |
| 154 | + /// | |
| 155 | + /// assert_eq!(Alignment::new::<0x10>().mask(), !0xf); | |
| 156 | + /// ``` | |
| 157 | + #[inline(always)] | |
| 158 | + pub const fn mask(self) -> usize { | |
| 159 | + // No underflow can occur as the alignment is guaranteed to be a power of two, and thus is | |
| 160 | + // non-zero. | |
| 161 | + !(self.as_usize() - 1) | |
| 162 | + } | |
| 163 | +} | |
| 164 | + | |
| 165 | +/// Trait for items that can be aligned against an [`Alignment`]. | |
| 166 | +pub trait Alignable: Sized { | |
| 167 | + /// Aligns `self` down to `alignment`. | |
| 168 | + /// | |
| 169 | + /// # Examples | |
| 170 | + /// | |
| 171 | + /// ``` | |
| 172 | + /// use kernel::ptr::{Alignable, Alignment}; | |
| 173 | + /// | |
| 174 | + /// assert_eq!(0x2f_usize.align_down(Alignment::new::<0x10>()), 0x20); | |
| 175 | + /// assert_eq!(0x30usize.align_down(Alignment::new::<0x10>()), 0x30); | |
| 176 | + /// assert_eq!(0xf0u8.align_down(Alignment::new::<0x1000>()), 0x0); | |
| 177 | + /// ``` | |
| 178 | + fn align_down(self, alignment: Alignment) -> Self; | |
| 179 | + | |
| 180 | + /// Aligns `self` up to `alignment`, returning `None` if aligning would result in an overflow. | |
| 181 | + /// | |
| 182 | + /// # Examples | |
| 183 | + /// | |
| 184 | + /// ``` | |
| 185 | + /// use kernel::ptr::{Alignable, Alignment}; | |
| 186 | + /// | |
| 187 | + /// assert_eq!(0x4fusize.align_up(Alignment::new::<0x10>()), Some(0x50)); | |
| 188 | + /// assert_eq!(0x40usize.align_up(Alignment::new::<0x10>()), Some(0x40)); | |
| 189 | + /// assert_eq!(0x0usize.align_up(Alignment::new::<0x10>()), Some(0x0)); | |
| 190 | + /// assert_eq!(u8::MAX.align_up(Alignment::new::<0x10>()), None); | |
| 191 | + /// assert_eq!(0x10u8.align_up(Alignment::new::<0x100>()), None); | |
| 192 | + /// assert_eq!(0x0u8.align_up(Alignment::new::<0x100>()), Some(0x0)); | |
| 193 | + /// ``` | |
| 194 | + fn align_up(self, alignment: Alignment) -> Option<Self>; | |
| 195 | +} | |
| 196 | + | |
| 197 | +/// Implement [`Alignable`] for unsigned integer types. | |
| 198 | +macro_rules! impl_alignable_uint { | |
| 199 | + ($($t:ty),*) => { | |
| 200 | + $( | |
| 201 | + impl Alignable for $t { | |
| 202 | + #[inline(always)] | |
| 203 | + fn align_down(self, alignment: Alignment) -> Self { | |
| 204 | + // The operands of `&` need to be of the same type so convert the alignment to | |
| 205 | + // `Self`. This means we need to compute the mask ourselves. | |
| 206 | + ::core::num::NonZero::<Self>::try_from(alignment.as_nonzero()) | |
| 207 | + .map(|align| self & !(align.get() - 1)) | |
| 208 | + // An alignment larger than `Self` always aligns down to `0`. | |
| 209 | + .unwrap_or(0) | |
| 210 | + } | |
| 211 | + | |
| 212 | + #[inline(always)] | |
| 213 | + fn align_up(self, alignment: Alignment) -> Option<Self> { | |
| 214 | + let aligned_down = self.align_down(alignment); | |
| 215 | + if self == aligned_down { | |
| 216 | + Some(aligned_down) | |
| 217 | + } else { | |
| 218 | + Self::try_from(alignment.as_usize()) | |
| 219 | + .ok() | |
| 220 | + .and_then(|align| aligned_down.checked_add(align)) | |
| 221 | + } | |
| 222 | + } | |
| 223 | + } | |
| 224 | + )* | |
| 225 | + }; | |
| 226 | +} | |
| 227 | + | |
| 228 | +impl_alignable_uint!(u8, u16, u32, u64, usize); | |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | //! |
| 5 | 5 | //! C header: [`include/linux/seq_file.h`](srctree/include/linux/seq_file.h) |
| 6 | 6 | |
| 7 | −use crate::{bindings, c_str, types::NotThreadSafe, types::Opaque}; | |
| 7 | +use crate::{bindings, c_str, fmt, types::NotThreadSafe, types::Opaque}; | |
| 8 | 8 | |
| 9 | 9 | /// A utility for generating the contents of a seq file. |
| 10 | 10 | #[repr(transparent)] |
| @@ -31,7 +31,7 @@ impl SeqFile { · 20 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | /// Used by the [`seq_print`] macro. |
| 33 | 33 | #[inline] |
| 34 | − pub fn call_printf(&self, args: core::fmt::Arguments<'_>) { | |
| 34 | + pub fn call_printf(&self, args: fmt::Arguments<'_>) { | |
| 35 | 35 | // SAFETY: Passing a void pointer to `Arguments` is valid for `%pA`. |
| 36 | 36 | unsafe { |
| 37 | 37 | bindings::seq_printf( |
| @@ -47,7 +47,7 @@ impl SeqFile { · 9 unmodified lines | ||
| 47 | 47 | #[macro_export] |
| 48 | 48 | macro_rules! seq_print { |
| 49 | 49 | ($m:expr, $($arg:tt)+) => ( |
| 50 | − $m.call_printf(format_args!($($arg)+)) | |
| 50 | + $m.call_printf($crate::prelude::fmt!($($arg)+)) | |
| 51 | 51 | ); |
| 52 | 52 | } |
| 53 | 53 | pub use seq_print; |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | use crate::{ |
| 20 | 20 | alloc::{AllocError, Flags, KBox}, |
| 21 | 21 | ffi::c_void, |
| 22 | + fmt, | |
| 22 | 23 | init::InPlaceInit, |
| 23 | 24 | sync::Refcount, |
| 24 | 25 | try_init, |
| @@ -27,7 +28,6 @@ use crate::{ · 2 unmodified lines | ||
| 27 | 28 | use core::{ |
| 28 | 29 | alloc::Layout, |
| 29 | 30 | borrow::{Borrow, BorrowMut}, |
| 30 | − fmt, | |
| 31 | 31 | marker::PhantomData, |
| 32 | 32 | mem::{ManuallyDrop, MaybeUninit}, |
| 33 | 33 | ops::{Deref, DerefMut}, |
| @@ -367,10 +367,10 @@ impl<T: ?Sized> Arc<T> { · 333 unmodified lines | ||
| 367 | 367 | } |
| 368 | 368 | } |
| 369 | 369 | |
| 370 | −// SAFETY: The pointer returned by `into_foreign` comes from a well aligned | |
| 371 | −// pointer to `ArcInner<T>`. | |
| 370 | +// SAFETY: The pointer returned by `into_foreign` was originally allocated as an | |
| 371 | +// `KBox<ArcInner<T>>`, so that type is what determines the alignment. | |
| 372 | 372 | unsafe impl<T: 'static> ForeignOwnable for Arc<T> { |
| 373 | − const FOREIGN_ALIGN: usize = core::mem::align_of::<ArcInner<T>>(); | |
| 373 | + const FOREIGN_ALIGN: usize = <KBox<ArcInner<T>> as ForeignOwnable>::FOREIGN_ALIGN; | |
| 374 | 374 | |
| 375 | 375 | type Borrowed<'a> = ArcBorrow<'a, T>; |
| 376 | 376 | type BorrowedMut<'a> = Self::Borrowed<'a>; |
| @@ -1,6 +1,21 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | |
| 3 | 3 | //! Internal reference counting support. |
| 4 | +//! | |
| 5 | +//! Many C types already have their own reference counting mechanism (e.g. by storing a | |
| 6 | +//! `refcount_t`). This module provides support for directly using their internal reference count | |
| 7 | +//! from Rust; instead of making users have to use an additional Rust-reference count in the form of | |
| 8 | +//! [`Arc`]. | |
| 9 | +//! | |
| 10 | +//! The smart pointer [`ARef<T>`] acts similarly to [`Arc<T>`] in that it holds a refcount on the | |
| 11 | +//! underlying object, but this refcount is internal to the object. It essentially is a Rust | |
| 12 | +//! implementation of the `get_` and `put_` pattern used in C for reference counting. | |
| 13 | +//! | |
| 14 | +//! To make use of [`ARef<MyType>`], `MyType` needs to implement [`AlwaysRefCounted`]. It is a trait | |
| 15 | +//! for accessing the internal reference count of an object of the `MyType` type. | |
| 16 | +//! | |
| 17 | +//! [`Arc`]: crate::sync::Arc | |
| 18 | +//! [`Arc<T>`]: crate::sync::Arc | |
| 4 | 19 | |
| 5 | 20 | use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull}; |
| 6 | 21 | |
| @@ -97,7 +112,7 @@ impl<T: AlwaysRefCounted> ARef<T> { · 90 unmodified lines | ||
| 97 | 112 | /// |
| 98 | 113 | /// ``` |
| 99 | 114 | /// use core::ptr::NonNull; |
| 100 | − /// use kernel::types::{ARef, AlwaysRefCounted}; | |
| 115 | + /// use kernel::sync::aref::{ARef, AlwaysRefCounted}; | |
| 101 | 116 | /// |
| 102 | 117 | /// struct Empty {} |
| 103 | 118 | /// |
| @@ -9,7 +9,8 @@ use crate::{ · 8 unmodified lines | ||
| 9 | 9 | ffi::{c_int, c_long, c_uint}, |
| 10 | 10 | mm::MmWithUser, |
| 11 | 11 | pid_namespace::PidNamespace, |
| 12 | − types::{ARef, NotThreadSafe, Opaque}, | |
| 12 | + sync::aref::ARef, | |
| 13 | + types::{NotThreadSafe, Opaque}, | |
| 13 | 14 | }; |
| 14 | 15 | use core::{ |
| 15 | 16 | cmp::{Eq, PartialEq}, |
| @@ -76,7 +77,7 @@ macro_rules! current { · 60 unmodified lines | ||
| 76 | 77 | /// incremented when creating `State` and decremented when it is dropped: |
| 77 | 78 | /// |
| 78 | 79 | /// ``` |
| 79 | −/// use kernel::{task::Task, types::ARef}; | |
| 80 | +/// use kernel::{task::Task, sync::aref::ARef}; | |
| 80 | 81 | /// |
| 81 | 82 | /// struct State { |
| 82 | 83 | /// creator: ARef<Task>, |
| @@ -347,7 +348,7 @@ impl CurrentTask { · 264 unmodified lines | ||
| 347 | 348 | } |
| 348 | 349 | |
| 349 | 350 | // SAFETY: The type invariants guarantee that `Task` is always refcounted. |
| 350 | −unsafe impl crate::types::AlwaysRefCounted for Task { | |
| 351 | +unsafe impl crate::sync::aref::AlwaysRefCounted for Task { | |
| 351 | 352 | #[inline] |
| 352 | 353 | fn inc_ref(&self) { |
| 353 | 354 | // SAFETY: The existence of a shared reference means that the refcount is nonzero. |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | //! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h). |
| 26 | 26 | |
| 27 | 27 | use core::marker::PhantomData; |
| 28 | +use core::ops; | |
| 28 | 29 | |
| 29 | 30 | pub mod delay; |
| 30 | 31 | pub mod hrtimer; |
| @@ -200,9 +201,31 @@ impl<C: ClockSource> Instant<C> { · 169 unmodified lines | ||
| 200 | 201 | pub(crate) fn as_nanos(&self) -> i64 { |
| 201 | 202 | self.inner |
| 202 | 203 | } |
| 204 | + | |
| 205 | + /// Create an [`Instant`] from a `ktime_t` without checking if it is non-negative. | |
| 206 | + /// | |
| 207 | + /// # Panics | |
| 208 | + /// | |
| 209 | + /// On debug builds, this function will panic if `ktime` is not in the range from 0 to | |
| 210 | + /// `KTIME_MAX`. | |
| 211 | + /// | |
| 212 | + /// # Safety | |
| 213 | + /// | |
| 214 | + /// The caller promises that `ktime` is in the range from 0 to `KTIME_MAX`. | |
| 215 | + #[inline] | |
| 216 | + pub(crate) unsafe fn from_ktime(ktime: bindings::ktime_t) -> Self { | |
| 217 | + debug_assert!(ktime >= 0); | |
| 218 | + | |
| 219 | + // INVARIANT: Our safety contract ensures that `ktime` is in the range from 0 to | |
| 220 | + // `KTIME_MAX`. | |
| 221 | + Self { | |
| 222 | + inner: ktime, | |
| 223 | + _c: PhantomData, | |
| 224 | + } | |
| 225 | + } | |
| 203 | 226 | } |
| 204 | 227 | |
| 205 | −impl<C: ClockSource> core::ops::Sub for Instant<C> { | |
| 228 | +impl<C: ClockSource> ops::Sub for Instant<C> { | |
| 206 | 229 | type Output = Delta; |
| 207 | 230 | |
| 208 | 231 | // By the type invariant, it never overflows. |
| @@ -214,6 +237,46 @@ impl<C: ClockSource> core::ops::Sub for Instant<C> { · 5 unmodified lines | ||
| 214 | 237 | } |
| 215 | 238 | } |
| 216 | 239 | |
| 240 | +impl<T: ClockSource> ops::Add<Delta> for Instant<T> { | |
| 241 | + type Output = Self; | |
| 242 | + | |
| 243 | + #[inline] | |
| 244 | + fn add(self, rhs: Delta) -> Self::Output { | |
| 245 | + // INVARIANT: With arithmetic over/underflow checks enabled, this will panic if we overflow | |
| 246 | + // (e.g. go above `KTIME_MAX`) | |
| 247 | + let res = self.inner + rhs.nanos; | |
| 248 | + | |
| 249 | + // INVARIANT: With overflow checks enabled, we verify here that the value is >= 0 | |
| 250 | + #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)] | |
| 251 | + assert!(res >= 0); | |
| 252 | + | |
| 253 | + Self { | |
| 254 | + inner: res, | |
| 255 | + _c: PhantomData, | |
| 256 | + } | |
| 257 | + } | |
| 258 | +} | |
| 259 | + | |
| 260 | +impl<T: ClockSource> ops::Sub<Delta> for Instant<T> { | |
| 261 | + type Output = Self; | |
| 262 | + | |
| 263 | + #[inline] | |
| 264 | + fn sub(self, rhs: Delta) -> Self::Output { | |
| 265 | + // INVARIANT: With arithmetic over/underflow checks enabled, this will panic if we overflow | |
| 266 | + // (e.g. go above `KTIME_MAX`) | |
| 267 | + let res = self.inner - rhs.nanos; | |
| 268 | + | |
| 269 | + // INVARIANT: With overflow checks enabled, we verify here that the value is >= 0 | |
| 270 | + #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)] | |
| 271 | + assert!(res >= 0); | |
| 272 | + | |
| 273 | + Self { | |
| 274 | + inner: res, | |
| 275 | + _c: PhantomData, | |
| 276 | + } | |
| 277 | + } | |
| 278 | +} | |
| 279 | + | |
| 217 | 280 | /// A span of time. |
| 218 | 281 | /// |
| 219 | 282 | /// This struct represents a span of time, with its value stored as nanoseconds. |
| @@ -224,6 +287,78 @@ pub struct Delta { · 4 unmodified lines | ||
| 224 | 287 | nanos: i64, |
| 225 | 288 | } |
| 226 | 289 | |
| 290 | +impl ops::Add for Delta { | |
| 291 | + type Output = Self; | |
| 292 | + | |
| 293 | + #[inline] | |
| 294 | + fn add(self, rhs: Self) -> Self { | |
| 295 | + Self { | |
| 296 | + nanos: self.nanos + rhs.nanos, | |
| 297 | + } | |
| 298 | + } | |
| 299 | +} | |
| 300 | + | |
| 301 | +impl ops::AddAssign for Delta { | |
| 302 | + #[inline] | |
| 303 | + fn add_assign(&mut self, rhs: Self) { | |
| 304 | + self.nanos += rhs.nanos; | |
| 305 | + } | |
| 306 | +} | |
| 307 | + | |
| 308 | +impl ops::Sub for Delta { | |
| 309 | + type Output = Self; | |
| 310 | + | |
| 311 | + #[inline] | |
| 312 | + fn sub(self, rhs: Self) -> Self::Output { | |
| 313 | + Self { | |
| 314 | + nanos: self.nanos - rhs.nanos, | |
| 315 | + } | |
| 316 | + } | |
| 317 | +} | |
| 318 | + | |
| 319 | +impl ops::SubAssign for Delta { | |
| 320 | + #[inline] | |
| 321 | + fn sub_assign(&mut self, rhs: Self) { | |
| 322 | + self.nanos -= rhs.nanos; | |
| 323 | + } | |
| 324 | +} | |
| 325 | + | |
| 326 | +impl ops::Mul<i64> for Delta { | |
| 327 | + type Output = Self; | |
| 328 | + | |
| 329 | + #[inline] | |
| 330 | + fn mul(self, rhs: i64) -> Self::Output { | |
| 331 | + Self { | |
| 332 | + nanos: self.nanos * rhs, | |
| 333 | + } | |
| 334 | + } | |
| 335 | +} | |
| 336 | + | |
| 337 | +impl ops::MulAssign<i64> for Delta { | |
| 338 | + #[inline] | |
| 339 | + fn mul_assign(&mut self, rhs: i64) { | |
| 340 | + self.nanos *= rhs; | |
| 341 | + } | |
| 342 | +} | |
| 343 | + | |
| 344 | +impl ops::Div for Delta { | |
| 345 | + type Output = i64; | |
| 346 | + | |
| 347 | + #[inline] | |
| 348 | + fn div(self, rhs: Self) -> Self::Output { | |
| 349 | + #[cfg(CONFIG_64BIT)] | |
| 350 | + { | |
| 351 | + self.nanos / rhs.nanos | |
| 352 | + } | |
| 353 | + | |
| 354 | + #[cfg(not(CONFIG_64BIT))] | |
| 355 | + { | |
| 356 | + // SAFETY: This function is always safe to call regardless of the input values | |
| 357 | + unsafe { bindings::div64_s64(self.nanos, rhs.nanos) } | |
| 358 | + } | |
| 359 | + } | |
| 360 | +} | |
| 361 | + | |
| 227 | 362 | impl Delta { |
| 228 | 363 | /// A span of time equal to zero. |
| 229 | 364 | pub const ZERO: Self = Self { nanos: 0 }; |
| @@ -312,4 +447,30 @@ impl Delta { · 82 unmodified lines | ||
| 312 | 447 | bindings::ktime_to_ms(self.as_nanos()) |
| 313 | 448 | } |
| 314 | 449 | } |
| 450 | + | |
| 451 | + /// Return `self % dividend` where `dividend` is in nanoseconds. | |
| 452 | + /// | |
| 453 | + /// The kernel doesn't have any emulation for `s64 % s64` on 32 bit platforms, so this is | |
| 454 | + /// limited to 32 bit dividends. | |
| 455 | + #[inline] | |
| 456 | + pub fn rem_nanos(self, dividend: i32) -> Self { | |
| 457 | + #[cfg(CONFIG_64BIT)] | |
| 458 | + { | |
| 459 | + Self { | |
| 460 | + nanos: self.as_nanos() % i64::from(dividend), | |
| 461 | + } | |
| 462 | + } | |
| 463 | + | |
| 464 | + #[cfg(not(CONFIG_64BIT))] | |
| 465 | + { | |
| 466 | + let mut rem = 0; | |
| 467 | + | |
| 468 | + // SAFETY: `rem` is in the stack, so we can always provide a valid pointer to it. | |
| 469 | + unsafe { bindings::div_s64_rem(self.as_nanos(), dividend, &mut rem) }; | |
| 470 | + | |
| 471 | + Self { | |
| 472 | + nanos: i64::from(rem), | |
| 473 | + } | |
| 474 | + } | |
| 475 | + } | |
| 315 | 476 | } |
| @@ -69,9 +69,14 @@ · 68 unmodified lines | ||
| 69 | 69 | |
| 70 | 70 | use super::{ClockSource, Delta, Instant}; |
| 71 | 71 | use crate::{prelude::*, types::Opaque}; |
| 72 | −use core::marker::PhantomData; | |
| 72 | +use core::{marker::PhantomData, ptr::NonNull}; | |
| 73 | 73 | use pin_init::PinInit; |
| 74 | 74 | |
| 75 | +/// A type-alias to refer to the [`Instant<C>`] for a given `T` from [`HrTimer<T>`]. | |
| 76 | +/// | |
| 77 | +/// Where `C` is the [`ClockSource`] of the [`HrTimer`]. | |
| 78 | +pub type HrTimerInstant<T> = Instant<<<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Clock>; | |
| 79 | + | |
| 75 | 80 | /// A timer backed by a C `struct hrtimer`. |
| 76 | 81 | /// |
| 77 | 82 | /// # Invariants |
| @@ -163,6 +168,84 @@ impl<T> HrTimer<T> { · 85 unmodified lines | ||
| 163 | 168 | // handled on the C side. |
| 164 | 169 | unsafe { bindings::hrtimer_cancel(c_timer_ptr) != 0 } |
| 165 | 170 | } |
| 171 | + | |
| 172 | + /// Forward the timer expiry for a given timer pointer. | |
| 173 | + /// | |
| 174 | + /// # Safety | |
| 175 | + /// | |
| 176 | + /// - `self_ptr` must point to a valid `Self`. | |
| 177 | + /// - The caller must either have exclusive access to the data pointed at by `self_ptr`, or be | |
| 178 | + /// within the context of the timer callback. | |
| 179 | + #[inline] | |
| 180 | + unsafe fn raw_forward(self_ptr: *mut Self, now: HrTimerInstant<T>, interval: Delta) -> u64 | |
| 181 | + where | |
| 182 | + T: HasHrTimer<T>, | |
| 183 | + { | |
| 184 | + // SAFETY: | |
| 185 | + // * The C API requirements for this function are fulfilled by our safety contract. | |
| 186 | + // * `self_ptr` is guaranteed to point to a valid `Self` via our safety contract | |
| 187 | + unsafe { | |
| 188 | + bindings::hrtimer_forward(Self::raw_get(self_ptr), now.as_nanos(), interval.as_nanos()) | |
| 189 | + } | |
| 190 | + } | |
| 191 | + | |
| 192 | + /// Conditionally forward the timer. | |
| 193 | + /// | |
| 194 | + /// If the timer expires after `now`, this function does nothing and returns 0. If the timer | |
| 195 | + /// expired at or before `now`, this function forwards the timer by `interval` until the timer | |
| 196 | + /// expires after `now` and then returns the number of times the timer was forwarded by | |
| 197 | + /// `interval`. | |
| 198 | + /// | |
| 199 | + /// This function is mainly useful for timer types which can provide exclusive access to the | |
| 200 | + /// timer when the timer is not running. For forwarding the timer from within the timer callback | |
| 201 | + /// context, see [`HrTimerCallbackContext::forward()`]. | |
| 202 | + /// | |
| 203 | + /// Returns the number of overruns that occurred as a result of the timer expiry change. | |
| 204 | + pub fn forward(self: Pin<&mut Self>, now: HrTimerInstant<T>, interval: Delta) -> u64 | |
| 205 | + where | |
| 206 | + T: HasHrTimer<T>, | |
| 207 | + { | |
| 208 | + // SAFETY: `raw_forward` does not move `Self` | |
| 209 | + let this = unsafe { self.get_unchecked_mut() }; | |
| 210 | + | |
| 211 | + // SAFETY: By existence of `Pin<&mut Self>`, the pointer passed to `raw_forward` points to a | |
| 212 | + // valid `Self` that we have exclusive access to. | |
| 213 | + unsafe { Self::raw_forward(this, now, interval) } | |
| 214 | + } | |
| 215 | + | |
| 216 | + /// Conditionally forward the timer. | |
| 217 | + /// | |
| 218 | + /// This is a variant of [`forward()`](Self::forward) that uses an interval after the current | |
| 219 | + /// time of the base clock for the [`HrTimer`]. | |
| 220 | + pub fn forward_now(self: Pin<&mut Self>, interval: Delta) -> u64 | |
| 221 | + where | |
| 222 | + T: HasHrTimer<T>, | |
| 223 | + { | |
| 224 | + self.forward(HrTimerInstant::<T>::now(), interval) | |
| 225 | + } | |
| 226 | + | |
| 227 | + /// Return the time expiry for this [`HrTimer`]. | |
| 228 | + /// | |
| 229 | + /// This value should only be used as a snapshot, as the actual expiry time could change after | |
| 230 | + /// this function is called. | |
| 231 | + pub fn expires(&self) -> HrTimerInstant<T> | |
| 232 | + where | |
| 233 | + T: HasHrTimer<T>, | |
| 234 | + { | |
| 235 | + // SAFETY: `self` is an immutable reference and thus always points to a valid `HrTimer`. | |
| 236 | + let c_timer_ptr = unsafe { HrTimer::raw_get(self) }; | |
| 237 | + | |
| 238 | + // SAFETY: | |
| 239 | + // - Timers cannot have negative ktime_t values as their expiration time. | |
| 240 | + // - There's no actual locking here, a racy read is fine and expected | |
| 241 | + unsafe { | |
| 242 | + Instant::from_ktime( | |
| 243 | + // This `read_volatile` is intended to correspond to a READ_ONCE call. | |
| 244 | + // FIXME(read_once): Replace with `read_once` when available on the Rust side. | |
| 245 | + core::ptr::read_volatile(&raw const ((*c_timer_ptr).node.expires)), | |
| 246 | + ) | |
| 247 | + } | |
| 248 | + } | |
| 166 | 249 | } |
| 167 | 250 | |
| 168 | 251 | /// Implemented by pointer types that point to structs that contain a [`HrTimer`]. |
| @@ -300,9 +383,13 @@ pub trait HrTimerCallback { · 131 unmodified lines | ||
| 300 | 383 | type Pointer<'a>: RawHrTimerCallback; |
| 301 | 384 | |
| 302 | 385 | /// Called by the timer logic when the timer fires. |
| 303 | − fn run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart | |
| 386 | + fn run( | |
| 387 | + this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>, | |
| 388 | + ctx: HrTimerCallbackContext<'_, Self>, | |
| 389 | + ) -> HrTimerRestart | |
| 304 | 390 | where |
| 305 | − Self: Sized; | |
| 391 | + Self: Sized, | |
| 392 | + Self: HasHrTimer<Self>; | |
| 306 | 393 | } |
| 307 | 394 | |
| 308 | 395 | /// A handle representing a potentially running timer. |
| @@ -324,6 +411,8 @@ pub unsafe trait HrTimerHandle { · 15 unmodified lines | ||
| 324 | 411 | /// Note that the timer might be started by a concurrent start operation. If |
| 325 | 412 | /// so, the timer might not be in the **stopped** state when this function |
| 326 | 413 | /// returns. |
| 414 | + /// | |
| 415 | + /// Returns `true` if the timer was running. | |
| 327 | 416 | fn cancel(&mut self) -> bool; |
| 328 | 417 | } |
| 329 | 418 | |
| @@ -585,6 +674,63 @@ impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> { · 255 unmodified lines | ||
| 585 | 674 | type Expires = Delta; |
| 586 | 675 | } |
| 587 | 676 | |
| 677 | +/// Privileged smart-pointer for a [`HrTimer`] callback context. | |
| 678 | +/// | |
| 679 | +/// Many [`HrTimer`] methods can only be called in two situations: | |
| 680 | +/// | |
| 681 | +/// * When the caller has exclusive access to the `HrTimer` and the `HrTimer` is guaranteed not to | |
| 682 | +/// be running. | |
| 683 | +/// * From within the context of an `HrTimer`'s callback method. | |
| 684 | +/// | |
| 685 | +/// This type provides access to said methods from within a timer callback context. | |
| 686 | +/// | |
| 687 | +/// # Invariants | |
| 688 | +/// | |
| 689 | +/// * The existence of this type means the caller is currently within the callback for an | |
| 690 | +/// [`HrTimer`]. | |
| 691 | +/// * `self.0` always points to a live instance of [`HrTimer<T>`]. | |
| 692 | +pub struct HrTimerCallbackContext<'a, T: HasHrTimer<T>>(NonNull<HrTimer<T>>, PhantomData<&'a ()>); | |
| 693 | + | |
| 694 | +impl<'a, T: HasHrTimer<T>> HrTimerCallbackContext<'a, T> { | |
| 695 | + /// Create a new [`HrTimerCallbackContext`]. | |
| 696 | + /// | |
| 697 | + /// # Safety | |
| 698 | + /// | |
| 699 | + /// This function relies on the caller being within the context of a timer callback, so it must | |
| 700 | + /// not be used anywhere except for within implementations of [`RawHrTimerCallback::run`]. The | |
| 701 | + /// caller promises that `timer` points to a valid initialized instance of | |
| 702 | + /// [`bindings::hrtimer`]. | |
| 703 | + /// | |
| 704 | + /// The returned `Self` must not outlive the function context of [`RawHrTimerCallback::run`] | |
| 705 | + /// where this function is called. | |
| 706 | + pub(crate) unsafe fn from_raw(timer: *mut HrTimer<T>) -> Self { | |
| 707 | + // SAFETY: The caller guarantees `timer` is a valid pointer to an initialized | |
| 708 | + // `bindings::hrtimer` | |
| 709 | + // INVARIANT: Our safety contract ensures that we're within the context of a timer callback | |
| 710 | + // and that `timer` points to a live instance of `HrTimer<T>`. | |
| 711 | + Self(unsafe { NonNull::new_unchecked(timer) }, PhantomData) | |
| 712 | + } | |
| 713 | + | |
| 714 | + /// Conditionally forward the timer. | |
| 715 | + /// | |
| 716 | + /// This function is identical to [`HrTimer::forward()`] except that it may only be used from | |
| 717 | + /// within the context of a [`HrTimer`] callback. | |
| 718 | + pub fn forward(&mut self, now: HrTimerInstant<T>, interval: Delta) -> u64 { | |
| 719 | + // SAFETY: | |
| 720 | + // - We are guaranteed to be within the context of a timer callback by our type invariants | |
| 721 | + // - By our type invariants, `self.0` always points to a valid `HrTimer<T>` | |
| 722 | + unsafe { HrTimer::<T>::raw_forward(self.0.as_ptr(), now, interval) } | |
| 723 | + } | |
| 724 | + | |
| 725 | + /// Conditionally forward the timer. | |
| 726 | + /// | |
| 727 | + /// This is a variant of [`HrTimerCallbackContext::forward()`] that uses an interval after the | |
| 728 | + /// current time of the base clock for the [`HrTimer`]. | |
| 729 | + pub fn forward_now(&mut self, duration: Delta) -> u64 { | |
| 730 | + self.forward(HrTimerInstant::<T>::now(), duration) | |
| 731 | + } | |
| 732 | +} | |
| 733 | + | |
| 588 | 734 | /// Use to implement the [`HasHrTimer<T>`] trait. |
| 589 | 735 | /// |
| 590 | 736 | /// See [`module`] documentation for an example. |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | use super::HasHrTimer; |
| 4 | 4 | use super::HrTimer; |
| 5 | 5 | use super::HrTimerCallback; |
| 6 | +use super::HrTimerCallbackContext; | |
| 6 | 7 | use super::HrTimerHandle; |
| 7 | 8 | use super::HrTimerMode; |
| 8 | 9 | use super::HrTimerPointer; |
| @@ -99,6 +100,12 @@ where · 90 unmodified lines | ||
| 99 | 100 | // allocation from other `Arc` clones. |
| 100 | 101 | let receiver = unsafe { ArcBorrow::from_raw(data_ptr) }; |
| 101 | 102 | |
| 102 | − T::run(receiver).into_c() | |
| 103 | + // SAFETY: | |
| 104 | + // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so | |
| 105 | + // it is a valid pointer to a `HrTimer<T>` embedded in a `T`. | |
| 106 | + // - We are within `RawHrTimerCallback::run` | |
| 107 | + let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) }; | |
| 108 | + | |
| 109 | + T::run(receiver, context).into_c() | |
| 103 | 110 | } |
| 104 | 111 | } |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | use super::HasHrTimer; |
| 4 | 4 | use super::HrTimer; |
| 5 | 5 | use super::HrTimerCallback; |
| 6 | +use super::HrTimerCallbackContext; | |
| 6 | 7 | use super::HrTimerHandle; |
| 7 | 8 | use super::HrTimerMode; |
| 8 | 9 | use super::RawHrTimerCallback; |
| @@ -103,6 +104,12 @@ where · 94 unmodified lines | ||
| 103 | 104 | // here. |
| 104 | 105 | let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) }; |
| 105 | 106 | |
| 106 | − T::run(receiver_pin).into_c() | |
| 107 | + // SAFETY: | |
| 108 | + // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so | |
| 109 | + // it is a valid pointer to a `HrTimer<T>` embedded in a `T`. | |
| 110 | + // - We are within `RawHrTimerCallback::run` | |
| 111 | + let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) }; | |
| 112 | + | |
| 113 | + T::run(receiver_pin, context).into_c() | |
| 107 | 114 | } |
| 108 | 115 | } |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | |
| 3 | 3 | use super::{ |
| 4 | − HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, HrTimerMode, RawHrTimerCallback, | |
| 5 | − UnsafeHrTimerPointer, | |
| 4 | + HasHrTimer, HrTimer, HrTimerCallback, HrTimerCallbackContext, HrTimerHandle, HrTimerMode, | |
| 5 | + RawHrTimerCallback, UnsafeHrTimerPointer, | |
| 6 | 6 | }; |
| 7 | 7 | use core::{marker::PhantomData, pin::Pin, ptr::NonNull}; |
| 8 | 8 | |
| @@ -107,6 +107,12 @@ where · 98 unmodified lines | ||
| 107 | 107 | // here. |
| 108 | 108 | let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) }; |
| 109 | 109 | |
| 110 | − T::run(receiver_pin).into_c() | |
| 110 | + // SAFETY: | |
| 111 | + // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so | |
| 112 | + // it is a valid pointer to a `HrTimer<T>` embedded in a `T`. | |
| 113 | + // - We are within `RawHrTimerCallback::run` | |
| 114 | + let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) }; | |
| 115 | + | |
| 116 | + T::run(receiver_pin, context).into_c() | |
| 111 | 117 | } |
| 112 | 118 | } |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | use super::HasHrTimer; |
| 4 | 4 | use super::HrTimer; |
| 5 | 5 | use super::HrTimerCallback; |
| 6 | +use super::HrTimerCallbackContext; | |
| 6 | 7 | use super::HrTimerHandle; |
| 7 | 8 | use super::HrTimerMode; |
| 8 | 9 | use super::HrTimerPointer; |
| @@ -119,6 +120,12 @@ where · 110 unmodified lines | ||
| 119 | 120 | // `data_ptr` exist. |
| 120 | 121 | let data_mut_ref = unsafe { Pin::new_unchecked(&mut *data_ptr) }; |
| 121 | 122 | |
| 122 | − T::run(data_mut_ref).into_c() | |
| 123 | + // SAFETY: | |
| 124 | + // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so | |
| 125 | + // it is a valid pointer to a `HrTimer<T>` embedded in a `T`. | |
| 126 | + // - We are within `RawHrTimerCallback::run` | |
| 127 | + let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) }; | |
| 128 | + | |
| 129 | + T::run(data_mut_ref, context).into_c() | |
| 123 | 130 | } |
| 124 | 131 | } |
| @@ -2,7 +2,6 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | use proc_macro::{TokenStream, TokenTree}; |
| 4 | 4 | |
| 5 | −#[allow(dead_code)] | |
| 6 | 5 | pub(crate) trait ToTokens { |
| 7 | 6 | fn to_tokens(&self, tokens: &mut TokenStream); |
| 8 | 7 | } |
| @@ -47,121 +46,116 @@ impl ToTokens for TokenStream { · 38 unmodified lines | ||
| 47 | 46 | /// `quote` crate but provides only just enough functionality needed by the current `macros` crate. |
| 48 | 47 | macro_rules! quote_spanned { |
| 49 | 48 | ($span:expr => $($tt:tt)*) => {{ |
| 50 | − let mut tokens: ::std::vec::Vec<::proc_macro::TokenTree>; | |
| 51 | − #[allow(clippy::vec_init_then_push)] | |
| 49 | + let mut tokens = ::proc_macro::TokenStream::new(); | |
| 52 | 50 | { |
| 53 | − tokens = ::std::vec::Vec::new(); | |
| 54 | 51 | let span = $span; |
| 55 | 52 | quote_spanned!(@proc tokens span $($tt)*); |
| 56 | 53 | } |
| 57 | − ::proc_macro::TokenStream::from_iter(tokens) | |
| 54 | + tokens | |
| 58 | 55 | }}; |
| 59 | 56 | (@proc $v:ident $span:ident) => {}; |
| 60 | 57 | (@proc $v:ident $span:ident #$id:ident $($tt:tt)*) => { |
| 61 | − let mut ts = ::proc_macro::TokenStream::new(); | |
| 62 | − $crate::quote::ToTokens::to_tokens(&$id, &mut ts); | |
| 63 | − $v.extend(ts); | |
| 58 | + $crate::quote::ToTokens::to_tokens(&$id, &mut $v); | |
| 64 | 59 | quote_spanned!(@proc $v $span $($tt)*); |
| 65 | 60 | }; |
| 66 | 61 | (@proc $v:ident $span:ident #(#$id:ident)* $($tt:tt)*) => { |
| 67 | 62 | for token in $id { |
| 68 | − let mut ts = ::proc_macro::TokenStream::new(); | |
| 69 | − $crate::quote::ToTokens::to_tokens(&token, &mut ts); | |
| 70 | − $v.extend(ts); | |
| 63 | + $crate::quote::ToTokens::to_tokens(&token, &mut $v); | |
| 71 | 64 | } |
| 72 | 65 | quote_spanned!(@proc $v $span $($tt)*); |
| 73 | 66 | }; |
| 74 | 67 | (@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) => { |
| 75 | 68 | #[allow(unused_mut)] |
| 76 | − let mut tokens = ::std::vec::Vec::<::proc_macro::TokenTree>::new(); | |
| 69 | + let mut tokens = ::proc_macro::TokenStream::new(); | |
| 77 | 70 | quote_spanned!(@proc tokens $span $($inner)*); |
| 78 | − $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new( | |
| 71 | + $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new( | |
| 79 | 72 | ::proc_macro::Delimiter::Parenthesis, |
| 80 | − ::proc_macro::TokenStream::from_iter(tokens) | |
| 81 | − ))); | |
| 73 | + tokens, | |
| 74 | + ))]); | |
| 82 | 75 | quote_spanned!(@proc $v $span $($tt)*); |
| 83 | 76 | }; |
| 84 | 77 | (@proc $v:ident $span:ident [ $($inner:tt)* ] $($tt:tt)*) => { |
| 85 | − let mut tokens = ::std::vec::Vec::new(); | |
| 78 | + let mut tokens = ::proc_macro::TokenStream::new(); | |
| 86 | 79 | quote_spanned!(@proc tokens $span $($inner)*); |
| 87 | − $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new( | |
| 80 | + $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new( | |
| 88 | 81 | ::proc_macro::Delimiter::Bracket, |
| 89 | − ::proc_macro::TokenStream::from_iter(tokens) | |
| 90 | − ))); | |
| 82 | + tokens, | |
| 83 | + ))]); | |
| 91 | 84 | quote_spanned!(@proc $v $span $($tt)*); |
| 92 | 85 | }; |
| 93 | 86 | (@proc $v:ident $span:ident { $($inner:tt)* } $($tt:tt)*) => { |
| 94 | − let mut tokens = ::std::vec::Vec::new(); | |
| 87 | + let mut tokens = ::proc_macro::TokenStream::new(); | |
| 95 | 88 | quote_spanned!(@proc tokens $span $($inner)*); |
| 96 | − $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new( | |
| 89 | + $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new( | |
| 97 | 90 | ::proc_macro::Delimiter::Brace, |
| 98 | − ::proc_macro::TokenStream::from_iter(tokens) | |
| 99 | − ))); | |
| 91 | + tokens, | |
| 92 | + ))]); | |
| 100 | 93 | quote_spanned!(@proc $v $span $($tt)*); |
| 101 | 94 | }; |
| 102 | 95 | (@proc $v:ident $span:ident :: $($tt:tt)*) => { |
| 103 | − $v.push(::proc_macro::TokenTree::Punct( | |
| 104 | − ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Joint) | |
| 105 | − )); | |
| 106 | − $v.push(::proc_macro::TokenTree::Punct( | |
| 107 | − ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone) | |
| 108 | − )); | |
| 96 | + $v.extend([::proc_macro::Spacing::Joint, ::proc_macro::Spacing::Alone].map(|spacing| { | |
| 97 | + ::proc_macro::TokenTree::Punct(::proc_macro::Punct::new(':', spacing)) | |
| 98 | + })); | |
| 109 | 99 | quote_spanned!(@proc $v $span $($tt)*); |
| 110 | 100 | }; |
| 111 | 101 | (@proc $v:ident $span:ident : $($tt:tt)*) => { |
| 112 | − $v.push(::proc_macro::TokenTree::Punct( | |
| 113 | − ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone) | |
| 114 | − )); | |
| 102 | + $v.extend([::proc_macro::TokenTree::Punct( | |
| 103 | + ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone), | |
| 104 | + )]); | |
| 115 | 105 | quote_spanned!(@proc $v $span $($tt)*); |
| 116 | 106 | }; |
| 117 | 107 | (@proc $v:ident $span:ident , $($tt:tt)*) => { |
| 118 | − $v.push(::proc_macro::TokenTree::Punct( | |
| 119 | − ::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone) | |
| 120 | − )); | |
| 108 | + $v.extend([::proc_macro::TokenTree::Punct( | |
| 109 | + ::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone), | |
| 110 | + )]); | |
| 121 | 111 | quote_spanned!(@proc $v $span $($tt)*); |
| 122 | 112 | }; |
| 123 | 113 | (@proc $v:ident $span:ident @ $($tt:tt)*) => { |
| 124 | − $v.push(::proc_macro::TokenTree::Punct( | |
| 125 | − ::proc_macro::Punct::new('@', ::proc_macro::Spacing::Alone) | |
| 126 | − )); | |
| 114 | + $v.extend([::proc_macro::TokenTree::Punct( | |
| 115 | + ::proc_macro::Punct::new('@', ::proc_macro::Spacing::Alone), | |
| 116 | + )]); | |
| 127 | 117 | quote_spanned!(@proc $v $span $($tt)*); |
| 128 | 118 | }; |
| 129 | 119 | (@proc $v:ident $span:ident ! $($tt:tt)*) => { |
| 130 | − $v.push(::proc_macro::TokenTree::Punct( | |
| 131 | − ::proc_macro::Punct::new('!', ::proc_macro::Spacing::Alone) | |
| 132 | − )); | |
| 120 | + $v.extend([::proc_macro::TokenTree::Punct( | |
| 121 | + ::proc_macro::Punct::new('!', ::proc_macro::Spacing::Alone), | |
| 122 | + )]); | |
| 133 | 123 | quote_spanned!(@proc $v $span $($tt)*); |
| 134 | 124 | }; |
| 135 | 125 | (@proc $v:ident $span:ident ; $($tt:tt)*) => { |
| 136 | − $v.push(::proc_macro::TokenTree::Punct( | |
| 137 | − ::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone) | |
| 138 | − )); | |
| 126 | + $v.extend([::proc_macro::TokenTree::Punct( | |
| 127 | + ::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone), | |
| 128 | + )]); | |
| 139 | 129 | quote_spanned!(@proc $v $span $($tt)*); |
| 140 | 130 | }; |
| 141 | 131 | (@proc $v:ident $span:ident + $($tt:tt)*) => { |
| 142 | − $v.push(::proc_macro::TokenTree::Punct( | |
| 143 | − ::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone) | |
| 144 | − )); | |
| 132 | + $v.extend([::proc_macro::TokenTree::Punct( | |
| 133 | + ::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone), | |
| 134 | + )]); | |
| 145 | 135 | quote_spanned!(@proc $v $span $($tt)*); |
| 146 | 136 | }; |
| 147 | 137 | (@proc $v:ident $span:ident = $($tt:tt)*) => { |
| 148 | − $v.push(::proc_macro::TokenTree::Punct( | |
| 149 | − ::proc_macro::Punct::new('=', ::proc_macro::Spacing::Alone) | |
| 150 | − )); | |
| 138 | + $v.extend([::proc_macro::TokenTree::Punct( | |
| 139 | + ::proc_macro::Punct::new('=', ::proc_macro::Spacing::Alone), | |
| 140 | + )]); | |
| 151 | 141 | quote_spanned!(@proc $v $span $($tt)*); |
| 152 | 142 | }; |
| 153 | 143 | (@proc $v:ident $span:ident # $($tt:tt)*) => { |
| 154 | − $v.push(::proc_macro::TokenTree::Punct( | |
| 155 | − ::proc_macro::Punct::new('#', ::proc_macro::Spacing::Alone) | |
| 156 | − )); | |
| 144 | + $v.extend([::proc_macro::TokenTree::Punct( | |
| 145 | + ::proc_macro::Punct::new('#', ::proc_macro::Spacing::Alone), | |
| 146 | + )]); | |
| 157 | 147 | quote_spanned!(@proc $v $span $($tt)*); |
| 158 | 148 | }; |
| 159 | 149 | (@proc $v:ident $span:ident _ $($tt:tt)*) => { |
| 160 | − $v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new("_", $span))); | |
| 150 | + $v.extend([::proc_macro::TokenTree::Ident( | |
| 151 | + ::proc_macro::Ident::new("_", $span), | |
| 152 | + )]); | |
| 161 | 153 | quote_spanned!(@proc $v $span $($tt)*); |
| 162 | 154 | }; |
| 163 | 155 | (@proc $v:ident $span:ident $id:ident $($tt:tt)*) => { |
| 164 | − $v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new(stringify!($id), $span))); | |
| 156 | + $v.extend([::proc_macro::TokenTree::Ident( | |
| 157 | + ::proc_macro::Ident::new(stringify!($id), $span), | |
| 158 | + )]); | |
| 165 | 159 | quote_spanned!(@proc $v $span $($tt)*); |
| 166 | 160 | }; |
| 167 | 161 | } |
| @@ -34,4 +34,6 @@ type __kernel_size_t = usize; · 33 unmodified lines | ||
| 34 | 34 | type __kernel_ssize_t = isize; |
| 35 | 35 | type __kernel_ptrdiff_t = isize; |
| 36 | 36 | |
| 37 | +use pin_init::MaybeZeroable; | |
| 38 | + | |
| 37 | 39 | include!(concat!(env!("OBJTREE"), "/rust/uapi/uapi_generated.rs")); |
| @@ -94,7 +94,7 @@ impl configfs::AttributeOperations<0> for Configuration { · 93 unmodified lines | ||
| 94 | 94 | |
| 95 | 95 | fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Result<usize> { |
| 96 | 96 | pr_info!("Show message\n"); |
| 97 | − let data = container.message; | |
| 97 | + let data = container.message.to_bytes(); | |
| 98 | 98 | page[0..data.len()].copy_from_slice(data); |
| 99 | 99 | Ok(data.len()) |
| 100 | 100 | } |
| @@ -10,7 +10,7 @@ use kernel::{ · 9 unmodified lines | ||
| 10 | 10 | dma::{CoherentAllocation, Device, DmaMask}, |
| 11 | 11 | pci, |
| 12 | 12 | prelude::*, |
| 13 | − types::ARef, | |
| 13 | + sync::aref::ARef, | |
| 14 | 14 | }; |
| 15 | 15 | |
| 16 | 16 | struct DmaSampleDriver { |
| @@ -139,8 +139,8 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit · 138 unmodified lines | ||
| 139 | 139 | "exclude_dirs": [], |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | − append_crate_with_generated("bindings", ["core", "ffi"]) | |
| 143 | − append_crate_with_generated("uapi", ["core", "ffi"]) | |
| 142 | + append_crate_with_generated("bindings", ["core", "ffi", "pin_init"]) | |
| 143 | + append_crate_with_generated("uapi", ["core", "ffi", "pin_init"]) | |
| 144 | 144 | append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"]) |
| 145 | 145 | |
| 146 | 146 | def is_root_crate(build_file, target): |
| @@ -202,7 +202,7 @@ pub extern "C" fn {kunit_name}(__kunit_test: *mut ::kernel::bindings::kunit) {{ · 201 unmodified lines | ||
| 202 | 202 | // This follows the syntax for declaring test metadata in the proposed KTAP v2 spec, which may |
| 203 | 203 | // be used for the proposed KUnit test attributes API. Thus hopefully this will make migration |
| 204 | 204 | // easier later on. |
| 205 | − ::kernel::kunit::info(format_args!(" # {kunit_name}.location: {real_path}:{line}\n")); | |
| 205 | + ::kernel::kunit::info(fmt!(" # {kunit_name}.location: {real_path}:{line}\n")); | |
| 206 | 206 | |
| 207 | 207 | /// The anchor where the test code body starts. |
| 208 | 208 | #[allow(unused)] |