Convert the paired #[cfg(CONFIG_FOO)] / #[cfg(not(CONFIG_FOO))] selections in the kernel crate to cfg_select!. These sites each choose one of several mutually-exclusive implementations, which is exactly what cfg_select! expresses as a single construct.
One case is deliberately left as #[cfg]: a #[macro_export] macro_rules! that is referred to by an absolute path ($crate::/crate::) cannot be wrapped in cfg_select!, because a macro produced by macro expansion may not be named that way (see rust-lang/rust#52234). print_macro in print.rs hits this and is kept as paired #[cfg]; macros invoked only by their bare name, such as the asm! wrapper in lib.rs, are unaffected and are converted. Link: https://github.com/Rust-for-Linux/linux/issues/1183 Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Nika Krasnova <[email protected]> --- rust/kernel/cpu.rs | 21 ++--- rust/kernel/cpumask.rs | 42 +++++----- rust/kernel/debugfs.rs | 145 ++++++++++++++++++----------------- rust/kernel/driver.rs | 44 ++++++----- rust/kernel/drm/device.rs | 53 +++++++------ rust/kernel/error.rs | 47 ++++++------ rust/kernel/kunit.rs | 54 +++++++------ rust/kernel/lib.rs | 77 ++++++++++--------- rust/kernel/mm.rs | 36 +++++---- rust/kernel/sync/atomic.rs | 54 +++++++------ rust/kernel/sync/atomic/predefine.rs | 35 +++++---- rust/kernel/time.rs | 82 ++++++++++---------- 12 files changed, 366 insertions(+), 324 deletions(-) diff --git a/rust/kernel/cpu.rs b/rust/kernel/cpu.rs index cb6c0338ef5a..b6730331fda8 100644 --- a/rust/kernel/cpu.rs +++ b/rust/kernel/cpu.rs @@ -4,20 +4,21 @@ //! //! C header: [`include/linux/cpu.h`](srctree/include/linux/cpu.h) -use crate::{bindings, device::Device, error::Result, prelude::ENODEV}; +use crate::{bindings, cfg_select, device::Device, error::Result, prelude::ENODEV}; /// Returns the maximum number of possible CPUs in the current system configuration. #[inline] pub fn nr_cpu_ids() -> u32 { - #[cfg(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS))] - { - bindings::NR_CPUS - } - - #[cfg(not(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS)))] - // SAFETY: `nr_cpu_ids` is a valid global provided by the kernel. - unsafe { - bindings::nr_cpu_ids + cfg_select! { + any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS) => { + bindings::NR_CPUS + } + _ => { + // SAFETY: `nr_cpu_ids` is a valid global provided by the kernel. + unsafe { + bindings::nr_cpu_ids + } + } } } diff --git a/rust/kernel/cpumask.rs b/rust/kernel/cpumask.rs index 44bb36636ee3..f86ec96acfe2 100644 --- a/rust/kernel/cpumask.rs +++ b/rust/kernel/cpumask.rs @@ -307,28 +307,34 @@ pub fn try_clone(cpumask: &Cpumask) -> Result<Self> { impl Deref for CpumaskVar { type Target = Cpumask; - #[cfg(CONFIG_CPUMASK_OFFSTACK)] - fn deref(&self) -> &Self::Target { - // SAFETY: The caller owns CpumaskVar, so it is safe to deref the cpumask. - unsafe { &*self.ptr.as_ptr() } - } - - #[cfg(not(CONFIG_CPUMASK_OFFSTACK))] - fn deref(&self) -> &Self::Target { - &self.mask + cfg_select! { + CONFIG_CPUMASK_OFFSTACK => { + fn deref(&self) -> &Self::Target { + // SAFETY: The caller owns CpumaskVar, so it is safe to deref the cpumask. + unsafe { &*self.ptr.as_ptr() } + } + } + _ => { + fn deref(&self) -> &Self::Target { + &self.mask + } + } } } impl DerefMut for CpumaskVar { - #[cfg(CONFIG_CPUMASK_OFFSTACK)] - fn deref_mut(&mut self) -> &mut Cpumask { - // SAFETY: The caller owns CpumaskVar, so it is safe to deref the cpumask. - unsafe { self.ptr.as_mut() } - } - - #[cfg(not(CONFIG_CPUMASK_OFFSTACK))] - fn deref_mut(&mut self) -> &mut Cpumask { - &mut self.mask + cfg_select! { + CONFIG_CPUMASK_OFFSTACK => { + fn deref_mut(&mut self) -> &mut Cpumask { + // SAFETY: The caller owns CpumaskVar, so it is safe to deref the cpumask. + unsafe { self.ptr.as_mut() } + } + } + _ => { + fn deref_mut(&mut self) -> &mut Cpumask { + &mut self.mask + } + } } } diff --git a/rust/kernel/debugfs.rs b/rust/kernel/debugfs.rs index d7b8014a6474..39657bfd1714 100644 --- a/rust/kernel/debugfs.rs +++ b/rust/kernel/debugfs.rs @@ -75,22 +75,22 @@ impl Dir { /// Create a new directory in DebugFS. If `parent` is [`None`], it will be created at the root. fn create(name: &CStr, parent: Option<&Dir>) -> Self { - #[cfg(CONFIG_DEBUG_FS)] - { - let parent_entry = match parent { - // If the parent couldn't be allocated, just early-return - Some(Dir(None)) => return Self(None), - Some(Dir(Some(entry))) => Some(entry.clone()), - None => None, - }; - Self( - // If Arc creation fails, the `Entry` will be dropped, so the directory will be - // cleaned up. - Arc::new(Entry::dynamic_dir(name, parent_entry), GFP_KERNEL).ok(), - ) + cfg_select! { + CONFIG_DEBUG_FS => { + let parent_entry = match parent { + // If the parent couldn't be allocated, just early-return + Some(Dir(None)) => return Self(None), + Some(Dir(Some(entry))) => Some(entry.clone()), + None => None, + }; + Self( + // If Arc creation fails, the `Entry` will be dropped, so the directory will be + // cleaned up. + Arc::new(Entry::dynamic_dir(name, parent_entry), GFP_KERNEL).ok(), + ) + } + _ => { Self() } } - #[cfg(not(CONFIG_DEBUG_FS))] - Self() } /// Creates a DebugFS file which will own the data produced by the initializer provided in @@ -360,19 +360,19 @@ pub fn write_callback_file<'a, T, E: 'a, W>( // Unless you also extract the `entry` later and schedule it for `Drop` at the appropriate // time, a `ScopedDir` with a `Dir` parent will never be deleted. fn scoped_dir<'data>(&self, name: &CStr) -> ScopedDir<'data, 'static> { - #[cfg(CONFIG_DEBUG_FS)] - { - let parent_entry = match &self.0 { - None => return ScopedDir::empty(), - Some(entry) => entry.clone(), - }; - ScopedDir { - entry: ManuallyDrop::new(Entry::dynamic_dir(name, Some(parent_entry))), - _phantom: PhantomData, + cfg_select! { + CONFIG_DEBUG_FS => { + let parent_entry = match &self.0 { + None => return ScopedDir::empty(), + Some(entry) => entry.clone(), + }; + ScopedDir { + entry: ManuallyDrop::new(Entry::dynamic_dir(name, Some(parent_entry))), + _phantom: PhantomData, + } } + _ => { ScopedDir::empty() } } - #[cfg(not(CONFIG_DEBUG_FS))] - ScopedDir::empty() } /// Creates a new scope, which is a directory associated with some data `T`. @@ -430,47 +430,50 @@ pub struct File<T> { scope: Scope<T>, } -#[cfg(not(CONFIG_DEBUG_FS))] -impl<'b, T: 'b> Scope<T> { - fn new<E: 'b, F>(data: impl PinInit<T, E> + 'b, init: F) -> impl PinInit<Self, E> + 'b - where - F: for<'a> FnOnce(&'a T) + 'b, - { - try_pin_init! { - Self { - data <- data, - _pin: PhantomPinned - } ? E - } - .pin_chain(|scope| { - init(&scope.data); - Ok(()) - }) - } -} +cfg_select! { + CONFIG_DEBUG_FS => { + impl<'b, T: 'b> Scope<T> { + fn entry_mut(self: Pin<&mut Self>) -> &mut Entry<'static> { + // SAFETY: _entry is not structurally pinned. + unsafe { &mut Pin::into_inner_unchecked(self)._entry } + } -#[cfg(CONFIG_DEBUG_FS)] -impl<'b, T: 'b> Scope<T> { - fn entry_mut(self: Pin<&mut Self>) -> &mut Entry<'static> { - // SAFETY: _entry is not structurally pinned. - unsafe { &mut Pin::into_inner_unchecked(self)._entry } + fn new<E: 'b, F>(data: impl PinInit<T, E> + 'b, init: F) -> impl PinInit<Self, E> + 'b + where + F: for<'a> FnOnce(&'a T) -> Entry<'static> + 'b, + { + try_pin_init! { + Self { + _entry: Entry::empty(), + data <- data, + _pin: PhantomPinned + } ? E + } + .pin_chain(|scope| { + *scope.entry_mut() = init(&scope.data); + Ok(()) + }) + } + } } - - fn new<E: 'b, F>(data: impl PinInit<T, E> + 'b, init: F) -> impl PinInit<Self, E> + 'b - where - F: for<'a> FnOnce(&'a T) -> Entry<'static> + 'b, - { - try_pin_init! { - Self { - _entry: Entry::empty(), - data <- data, - _pin: PhantomPinned - } ? E + _ => { + impl<'b, T: 'b> Scope<T> { + fn new<E: 'b, F>(data: impl PinInit<T, E> + 'b, init: F) -> impl PinInit<Self, E> + 'b + where + F: for<'a> FnOnce(&'a T) + 'b, + { + try_pin_init! { + Self { + data <- data, + _pin: PhantomPinned + } ? E + } + .pin_chain(|scope| { + init(&scope.data); + Ok(()) + }) + } } - .pin_chain(|scope| { - *scope.entry_mut() = init(&scope.data); - Ok(()) - }) } } @@ -702,12 +705,16 @@ fn empty() -> Self { _phantom: PhantomData, } } - #[cfg(CONFIG_DEBUG_FS)] - fn into_entry(self) -> Entry<'dir> { - ManuallyDrop::into_inner(self.entry) + cfg_select! { + CONFIG_DEBUG_FS => { + fn into_entry(self) -> Entry<'dir> { + ManuallyDrop::into_inner(self.entry) + } + } + _ => { + fn into_entry(self) {} + } } - #[cfg(not(CONFIG_DEBUG_FS))] - fn into_entry(self) {} } impl<'data> ScopedDir<'data, 'static> { diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs index bf5ba0d27553..871ea9e04804 100644 --- a/rust/kernel/driver.rs +++ b/rust/kernel/driver.rs @@ -328,29 +328,31 @@ pub trait Adapter { /// /// If this returns `None`, it means there is no match with an entry in the [`acpi::IdTable`]. fn acpi_id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> { - #[cfg(not(CONFIG_ACPI))] - { - let _ = dev; - None - } + cfg_select! { + CONFIG_ACPI => { + let table = Self::acpi_id_table()?; - #[cfg(CONFIG_ACPI)] - { - let table = Self::acpi_id_table()?; - - // SAFETY: - // - `table` has static lifetime, hence it's valid for read, - // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`. - let raw_id = unsafe { bindings::acpi_match_device(table.as_ptr(), dev.as_raw()) }; - - if raw_id.is_null() { + // SAFETY: + // - `table` has static lifetime, hence it's valid for read, + // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`. + let raw_id = unsafe { bindings::acpi_match_device(table.as_ptr(), dev.as_raw()) }; + + if raw_id.is_null() { + None + } else { + // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of + // `struct acpi_device_id` and does not add additional invariants, so + // it's safe to transmute. + let id = unsafe { &*raw_id.cast::<acpi::DeviceId>() }; + + Some(table.info( + <acpi::DeviceId as crate::device_id::RawDeviceIdIndex>::index(id), + )) + } + } + _ => { + let _ = dev; None - } else { - // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct acpi_device_id` - // and does not add additional invariants, so it's safe to transmute. - let id = unsafe { &*raw_id.cast::<acpi::DeviceId>() }; - - Some(table.info(<acpi::DeviceId as crate::device_id::RawDeviceIdIndex>::index(id))) } } } diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index 477cf771fb10..61a184241d55 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -41,33 +41,36 @@ }, }; -#[cfg(CONFIG_DRM_LEGACY)] -macro_rules! drm_legacy_fields { - ( $($field:ident: $val:expr),* $(,)? ) => { - bindings::drm_driver { - $( $field: $val ),*, - firstopen: None, - preclose: None, - dma_ioctl: None, - dma_quiescent: None, - context_dtor: None, - irq_handler: None, - irq_preinstall: None, - irq_postinstall: None, - irq_uninstall: None, - get_vblank_counter: None, - enable_vblank: None, - disable_vblank: None, - dev_priv_size: 0, +cfg_select! { + CONFIG_DRM_LEGACY => { + macro_rules! drm_legacy_fields { + ( $($field:ident: $val:expr),* $(,)? ) => { + bindings::drm_driver { + $( $field: $val ),*, + firstopen: None, + preclose: None, + dma_ioctl: None, + dma_quiescent: None, + context_dtor: None, + irq_handler: None, + irq_preinstall: None, + irq_postinstall: None, + irq_uninstall: None, + get_vblank_counter: None, + enable_vblank: None, + disable_vblank: None, + dev_priv_size: 0, + } + } } } -} - -#[cfg(not(CONFIG_DRM_LEGACY))] -macro_rules! drm_legacy_fields { - ( $($field:ident: $val:expr),* $(,)? ) => { - bindings::drm_driver { - $( $field: $val ),* + _ => { + macro_rules! drm_legacy_fields { + ( $($field:ident: $val:expr),* $(,)? ) => { + bindings::drm_driver { + $( $field: $val ),* + } + } } } } diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index a56ba6309594..733c2d08c5e6 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -8,7 +8,7 @@ use crate::{ alloc::{layout::LayoutError, AllocError}, - fmt, + cfg_select, fmt, str::CStr, }; @@ -173,29 +173,32 @@ pub fn to_ptr<T>(self) -> *mut T { unsafe { bindings::ERR_PTR(self.0.get() as crate::ffi::c_long).cast() } } - /// Returns a string representing the error, if one exists. - #[cfg(not(testlib))] - pub fn name(&self) -> Option<&'static CStr> { - // SAFETY: Just an FFI call, there are no extra safety requirements. - let ptr = unsafe { bindings::errname(-self.0.get()) }; - if ptr.is_null() { - None - } else { - use crate::str::CStrExt as _; - - // SAFETY: The string returned by `errname` is static and `NUL`-terminated. - Some(unsafe { CStr::from_char_ptr(ptr) }) + cfg_select! { + testlib => { + /// Returns a string representing the error, if one exists. + /// + /// When `testlib` is configured, this always returns `None` to avoid + /// the dependency on a kernel function so that tests that use this + /// (e.g., by calling [`Result::unwrap`]) can still run in userspace. + pub fn name(&self) -> Option<&'static CStr> { + None + } } - } + _ => { + /// Returns a string representing the error, if one exists. + pub fn name(&self) -> Option<&'static CStr> { + // SAFETY: Just an FFI call, there are no extra safety requirements. + let ptr = unsafe { bindings::errname(-self.0.get()) }; + if ptr.is_null() { + None + } else { + use crate::str::CStrExt as _; - /// Returns a string representing the error, if one exists. - /// - /// When `testlib` is configured, this always returns `None` to avoid the dependency on a - /// kernel function so that tests that use this (e.g., by calling [`Result::unwrap`]) can still - /// run in userspace. - #[cfg(testlib)] - pub fn name(&self) -> Option<&'static CStr> { - None + // SAFETY: The string returned by `errname` is static and `NUL`-terminated. + Some(unsafe { CStr::from_char_ptr(ptr) }) + } + } + } } } diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs index cdee5f27bd7f..5ec15bfbfee6 100644 --- a/rust/kernel/kunit.rs +++ b/rust/kernel/kunit.rs @@ -14,18 +14,21 @@ /// Public but hidden since it should only be used from KUnit generated code. #[doc(hidden)] pub fn err(args: fmt::Arguments<'_>) { - // `args` is unused if `CONFIG_PRINTK` is not set - this avoids a build-time warning. - #[cfg(not(CONFIG_PRINTK))] - let _ = args; - - // SAFETY: The format string is null-terminated and the `%pA` specifier matches the argument we - // are passing. - #[cfg(CONFIG_PRINTK)] - unsafe { - bindings::_printk( - c"\x013%pA".as_char_ptr(), - core::ptr::from_ref(&args).cast::<c_void>(), - ); + cfg_select! { + CONFIG_PRINTK => { + // SAFETY: The format string is null-terminated and the `%pA` specifier matches the + // argument we are passing. + unsafe { + bindings::_printk( + c"\x013%pA".as_char_ptr(), + core::ptr::from_ref(&args).cast::<c_void>(), + ); + } + } + _ => { + // `args` is unused if `CONFIG_PRINTK` is not set - this avoids a build-time warning. + let _ = args; + } } } @@ -34,18 +37,21 @@ pub fn err(args: fmt::Arguments<'_>) { /// Public but hidden since it should only be used from KUnit generated code. #[doc(hidden)] pub fn info(args: fmt::Arguments<'_>) { - // `args` is unused if `CONFIG_PRINTK` is not set - this avoids a build-time warning. - #[cfg(not(CONFIG_PRINTK))] - let _ = args; - - // SAFETY: The format string is null-terminated and the `%pA` specifier matches the argument we - // are passing. - #[cfg(CONFIG_PRINTK)] - unsafe { - bindings::_printk( - c"\x016%pA".as_char_ptr(), - core::ptr::from_ref(&args).cast::<c_void>(), - ); + cfg_select! { + CONFIG_PRINTK => { + // SAFETY: The format string is null-terminated and the `%pA` specifier matches the + // argument we are passing. + unsafe { + bindings::_printk( + c"\x016%pA".as_char_ptr(), + core::ptr::from_ref(&args).cast::<c_void>(), + ); + } + } + _ => { + // `args` is unused if `CONFIG_PRINTK` is not set - this avoids a build-time warning. + let _ = args; + } } } diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index cdcbb34047c0..ba233a037fe6 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -276,30 +276,34 @@ macro_rules! concat_literals { }; } -/// Wrapper around `asm!` configured for use in the kernel. -/// -/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!` -/// syntax. -// For x86, `asm!` uses intel syntax by default, but we want to use at&t syntax in the kernel. -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -#[macro_export] -macro_rules! asm { - ($($asm:expr),* ; $($rest:tt)*) => { - ::core::arch::asm!( $($asm)*, options(att_syntax), $($rest)* ) - }; -} - -/// Wrapper around `asm!` configured for use in the kernel. -/// -/// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!` -/// syntax. -// For non-x86 arches we just pass through to `asm!`. -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -#[macro_export] -macro_rules! asm { - ($($asm:expr),* ; $($rest:tt)*) => { - ::core::arch::asm!( $($asm)*, $($rest)* ) - }; +cfg_select! { + any(target_arch = "x86", target_arch = "x86_64") => { + /// Wrapper around `asm!` configured for use in the kernel. + /// + /// Uses a semicolon to avoid parsing ambiguities, even though this does + /// not match native `asm!` syntax. + // For x86, `asm!` uses intel syntax by default, but we want to use at&t + // syntax in the kernel. + #[macro_export] + macro_rules! asm { + ($($asm:expr),* ; $($rest:tt)*) => { + ::core::arch::asm!( $($asm)*, options(att_syntax), $($rest)* ) + }; + } + } + _ => { + /// Wrapper around `asm!` configured for use in the kernel. + /// + /// Uses a semicolon to avoid parsing ambiguities, even though this does + /// not match native `asm!` syntax. + // For non-x86 arches we just pass through to `asm!`. + #[macro_export] + macro_rules! asm { + ($($asm:expr),* ; $($rest:tt)*) => { + ::core::arch::asm!( $($asm)*, $($rest)* ) + }; + } + } } /// Gets the C string file name of a [`Location`]. @@ -334,19 +338,16 @@ macro_rules! asm { /// ``` #[inline] pub fn file_from_location<'a>(loc: &'a core::panic::Location<'a>) -> &'a core::ffi::CStr { - #[cfg(CONFIG_RUSTC_HAS_FILE_AS_C_STR)] - { - loc.file_as_c_str() - } - - #[cfg(all(CONFIG_RUSTC_HAS_FILE_WITH_NUL, not(CONFIG_RUSTC_HAS_FILE_AS_C_STR)))] - { - loc.file_with_nul() - } - - #[cfg(not(CONFIG_RUSTC_HAS_FILE_WITH_NUL))] - { - let _ = loc; - c"<Location::file_as_c_str() not supported>" + cfg_select! { + CONFIG_RUSTC_HAS_FILE_AS_C_STR => { + loc.file_as_c_str() + } + all(CONFIG_RUSTC_HAS_FILE_WITH_NUL, not(CONFIG_RUSTC_HAS_FILE_AS_C_STR)) => { + loc.file_with_nul() + } + not(CONFIG_RUSTC_HAS_FILE_WITH_NUL) => { + let _ = loc; + c"<Location::file_as_c_str() not supported>" + } } } diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs index 4764d7b68f2a..b3937d37b3a2 100644 --- a/rust/kernel/mm.rs +++ b/rust/kernel/mm.rs @@ -12,7 +12,7 @@ //! C header: [`include/linux/mm.h`](srctree/include/linux/mm.h) use crate::{ - bindings, + bindings, cfg_select, sync::aref::{ARef, AlwaysRefCounted}, types::{NotThreadSafe, Opaque}, }; @@ -174,25 +174,27 @@ pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_struct) -> &'a MmWithUser { /// When per-vma locks are disabled, this always returns `None`. #[inline] pub fn lock_vma_under_rcu(&self, vma_addr: usize) -> Option<VmaReadGuard<'_>> { - #[cfg(CONFIG_PER_VMA_LOCK)] - { - // SAFETY: Calling `bindings::lock_vma_under_rcu` is always okay given an mm where - // `mm_users` is non-zero. - let vma = unsafe { bindings::lock_vma_under_rcu(self.as_raw(), vma_addr) }; - if !vma.is_null() { - return Some(VmaReadGuard { - // SAFETY: If `lock_vma_under_rcu` returns a non-null ptr, then it points at a - // valid vma. The vma is stable for as long as the vma read lock is held. - vma: unsafe { VmaRef::from_raw(vma) }, - _nts: NotThreadSafe, - }); + cfg_select! { + CONFIG_PER_VMA_LOCK => { + // SAFETY: Calling `bindings::lock_vma_under_rcu` is always okay given an mm where + // `mm_users` is non-zero. + let vma = unsafe { bindings::lock_vma_under_rcu(self.as_raw(), vma_addr) }; + if !vma.is_null() { + return Some(VmaReadGuard { + // SAFETY: If `lock_vma_under_rcu` returns a non-null ptr, then it + // points at a valid vma. The vma is stable for as long as the vma + // read lock is held. + vma: unsafe { VmaRef::from_raw(vma) }, + _nts: NotThreadSafe, + }); + } + } + _ => { + // Silence warnings about unused variables. + let _ = vma_addr; } } - // Silence warnings about unused variables. - #[cfg(not(CONFIG_PER_VMA_LOCK))] - let _ = vma_addr; - None } diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs index 9cd009d57e35..d67dc44e8b2e 100644 --- a/rust/kernel/sync/atomic.rs +++ b/rust/kernel/sync/atomic.rs @@ -26,6 +26,7 @@ pub(crate) use internal::{AtomicArithmeticOps, AtomicBasicOps, AtomicExchangeOps}; use crate::build_error; +use crate::cfg_select; use internal::AtomicRepr; use ordering::OrderingType; @@ -620,25 +621,28 @@ pub fn fetch_sub<Rhs, Ordering: ordering::Ordering>(&self, v: Rhs, _: Ordering) } } -#[cfg(any(CONFIG_X86_64, CONFIG_UML, CONFIG_ARM, CONFIG_ARM64))] -#[repr(C)] -#[derive(Clone, Copy)] -struct Flag { - bool_field: bool, -} - -/// # Invariants -/// -/// `padding` must be all zeroes. -#[cfg(not(any(CONFIG_X86_64, CONFIG_UML, CONFIG_ARM, CONFIG_ARM64)))] -#[repr(C, align(4))] -#[derive(Clone, Copy)] -struct Flag { - #[cfg(target_endian = "big")] - padding: [u8; 3], - bool_field: bool, - #[cfg(target_endian = "little")] - padding: [u8; 3], +cfg_select! { + any(CONFIG_X86_64, CONFIG_UML, CONFIG_ARM, CONFIG_ARM64) => { + #[repr(C)] + #[derive(Clone, Copy)] + struct Flag { + bool_field: bool, + } + } + _ => { + /// # Invariants + /// + /// `padding` must be all zeroes. + #[repr(C, align(4))] + #[derive(Clone, Copy)] + struct Flag { + #[cfg(target_endian = "big")] + padding: [u8; 3], + bool_field: bool, + #[cfg(target_endian = "little")] + padding: [u8; 3], + } + } } impl Flag { @@ -656,10 +660,14 @@ const fn new(b: bool) -> Self { // SAFETY: `Flag` and `Repr` have the same size and alignment, and `Flag` is round-trip // transmutable to the selected representation (`i8` or `i32`). unsafe impl AtomicType for Flag { - #[cfg(any(CONFIG_X86_64, CONFIG_UML, CONFIG_ARM, CONFIG_ARM64))] - type Repr = i8; - #[cfg(not(any(CONFIG_X86_64, CONFIG_UML, CONFIG_ARM, CONFIG_ARM64)))] - type Repr = i32; + cfg_select! { + any(CONFIG_X86_64, CONFIG_UML, CONFIG_ARM, CONFIG_ARM64) => { + type Repr = i8; + } + _ => { + type Repr = i32; + } + } } /// An atomic flag type intended to be backed by performance-optimal integer type. diff --git a/rust/kernel/sync/atomic/predefine.rs b/rust/kernel/sync/atomic/predefine.rs index 3d63f40791fa..7156e9b67c8c 100644 --- a/rust/kernel/sync/atomic/predefine.rs +++ b/rust/kernel/sync/atomic/predefine.rs @@ -76,23 +76,24 @@ fn rhs_into_delta(rhs: i64) -> i64 { // Defines an internal type that always maps to the integer type which has the same size alignment // as `isize` and `usize`, and `isize` and `usize` are always bi-directional transmutable to // `isize_atomic_repr`, which also always implements `AtomicImpl`. -#[allow(non_camel_case_types)] -#[cfg(not(testlib))] -#[cfg(not(CONFIG_64BIT))] -type isize_atomic_repr = i32; -#[allow(non_camel_case_types)] -#[cfg(not(testlib))] -#[cfg(CONFIG_64BIT)] -type isize_atomic_repr = i64; - -#[allow(non_camel_case_types)] -#[cfg(testlib)] -#[cfg(target_pointer_width = "32")] -type isize_atomic_repr = i32; -#[allow(non_camel_case_types)] -#[cfg(testlib)] -#[cfg(target_pointer_width = "64")] -type isize_atomic_repr = i64; +cfg_select! { + all(not(testlib), not(CONFIG_64BIT)) => { + #[allow(non_camel_case_types)] + type isize_atomic_repr = i32; + } + all(not(testlib), CONFIG_64BIT) => { + #[allow(non_camel_case_types)] + type isize_atomic_repr = i64; + } + all(testlib, target_pointer_width = "32") => { + #[allow(non_camel_case_types)] + type isize_atomic_repr = i32; + } + all(testlib, target_pointer_width = "64") => { + #[allow(non_camel_case_types)] + type isize_atomic_repr = i64; + } +} // Ensure size and alignment requirements are checked. static_assert!(size_of::<isize>() == size_of::<isize_atomic_repr>()); diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs index 363e93cbb139..5cca5b9d111e 100644 --- a/rust/kernel/time.rs +++ b/rust/kernel/time.rs @@ -27,6 +27,8 @@ use core::marker::PhantomData; use core::ops; +use crate::cfg_select; + pub mod delay; pub mod hrtimer; @@ -360,15 +362,14 @@ impl ops::Div for Delta { #[inline] fn div(self, rhs: Self) -> Self::Output { - #[cfg(CONFIG_64BIT)] - { - self.nanos / rhs.nanos - } - - #[cfg(not(CONFIG_64BIT))] - { - // SAFETY: This function is always safe to call regardless of the input values - unsafe { bindings::div64_s64(self.nanos, rhs.nanos) } + cfg_select! { + CONFIG_64BIT => { + self.nanos / rhs.nanos + } + _ => { + // SAFETY: This function is always safe to call regardless of the input values + unsafe { bindings::div64_s64(self.nanos, rhs.nanos) } + } } } } @@ -441,30 +442,32 @@ pub const fn as_nanos(self) -> i64 { /// to the value in the [`Delta`]. #[inline] pub fn as_micros_ceil(self) -> i64 { - #[cfg(CONFIG_64BIT)] - { - self.as_nanos().saturating_add(NSEC_PER_USEC - 1) / NSEC_PER_USEC - } - - #[cfg(not(CONFIG_64BIT))] - // SAFETY: It is always safe to call `ktime_to_us()` with any value. - unsafe { - bindings::ktime_to_us(self.as_nanos().saturating_add(NSEC_PER_USEC - 1)) + cfg_select! { + CONFIG_64BIT => { + self.as_nanos().saturating_add(NSEC_PER_USEC - 1) / NSEC_PER_USEC + } + _ => { + // SAFETY: It is always safe to call `ktime_to_us()` with any value. + unsafe { + bindings::ktime_to_us(self.as_nanos().saturating_add(NSEC_PER_USEC - 1)) + } + } } } /// Return the number of milliseconds in the [`Delta`]. #[inline] pub fn as_millis(self) -> i64 { - #[cfg(CONFIG_64BIT)] - { - self.as_nanos() / NSEC_PER_MSEC - } - - #[cfg(not(CONFIG_64BIT))] - // SAFETY: It is always safe to call `ktime_to_ms()` with any value. - unsafe { - bindings::ktime_to_ms(self.as_nanos()) + cfg_select! { + CONFIG_64BIT => { + self.as_nanos() / NSEC_PER_MSEC + } + _ => { + // SAFETY: It is always safe to call `ktime_to_ms()` with any value. + unsafe { + bindings::ktime_to_ms(self.as_nanos()) + } + } } } @@ -474,22 +477,21 @@ pub fn as_millis(self) -> i64 { /// limited to 32 bit dividends. #[inline] pub fn rem_nanos(self, dividend: i32) -> Self { - #[cfg(CONFIG_64BIT)] - { - Self { - nanos: self.as_nanos() % i64::from(dividend), + cfg_select! { + CONFIG_64BIT => { + Self { + nanos: self.as_nanos() % i64::from(dividend), + } } - } - - #[cfg(not(CONFIG_64BIT))] - { - let mut rem = 0; + _ => { + let mut rem = 0; - // SAFETY: `rem` is in the stack, so we can always provide a valid pointer to it. - unsafe { bindings::div_s64_rem(self.as_nanos(), dividend, &mut rem) }; + // SAFETY: `rem` is in the stack, so we can always provide a valid pointer to it. + unsafe { bindings::div_s64_rem(self.as_nanos(), dividend, &mut rem) }; - Self { - nanos: i64::from(rem), + Self { + nanos: i64::from(rem), + } } } } -- 2.54.0

