Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rust: cpu: Introduce CpuId abstraction

This adds abstraction for representing a CPU identifier.

Suggested-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>

+110
+110
rust/kernel/cpu.rs
··· 6 6 7 7 use crate::{bindings, device::Device, error::Result, prelude::ENODEV}; 8 8 9 + /// Returns the maximum number of possible CPUs in the current system configuration. 10 + #[inline] 11 + pub fn nr_cpu_ids() -> u32 { 12 + #[cfg(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS))] 13 + { 14 + bindings::NR_CPUS 15 + } 16 + 17 + #[cfg(not(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS)))] 18 + // SAFETY: `nr_cpu_ids` is a valid global provided by the kernel. 19 + unsafe { 20 + bindings::nr_cpu_ids 21 + } 22 + } 23 + 24 + /// The CPU ID. 25 + /// 26 + /// Represents a CPU identifier as a wrapper around an [`u32`]. 27 + /// 28 + /// # Invariants 29 + /// 30 + /// The CPU ID lies within the range `[0, nr_cpu_ids())`. 31 + /// 32 + /// # Examples 33 + /// 34 + /// ``` 35 + /// use kernel::cpu::CpuId; 36 + /// 37 + /// let cpu = 0; 38 + /// 39 + /// // SAFETY: 0 is always a valid CPU number. 40 + /// let id = unsafe { CpuId::from_u32_unchecked(cpu) }; 41 + /// 42 + /// assert_eq!(id.as_u32(), cpu); 43 + /// assert!(CpuId::from_i32(0).is_some()); 44 + /// assert!(CpuId::from_i32(-1).is_none()); 45 + /// ``` 46 + #[derive(Copy, Clone, PartialEq, Eq, Debug)] 47 + pub struct CpuId(u32); 48 + 49 + impl CpuId { 50 + /// Creates a new [`CpuId`] from the given `id` without checking bounds. 51 + /// 52 + /// # Safety 53 + /// 54 + /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`). 55 + #[inline] 56 + pub unsafe fn from_i32_unchecked(id: i32) -> Self { 57 + debug_assert!(id >= 0); 58 + debug_assert!((id as u32) < nr_cpu_ids()); 59 + 60 + // INVARIANT: The function safety guarantees `id` is a valid CPU id. 61 + Self(id as u32) 62 + } 63 + 64 + /// Creates a new [`CpuId`] from the given `id`, checking that it is valid. 65 + pub fn from_i32(id: i32) -> Option<Self> { 66 + if id < 0 || id as u32 >= nr_cpu_ids() { 67 + None 68 + } else { 69 + // INVARIANT: `id` has just been checked as a valid CPU ID. 70 + Some(Self(id as u32)) 71 + } 72 + } 73 + 74 + /// Creates a new [`CpuId`] from the given `id` without checking bounds. 75 + /// 76 + /// # Safety 77 + /// 78 + /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`). 79 + #[inline] 80 + pub unsafe fn from_u32_unchecked(id: u32) -> Self { 81 + debug_assert!(id < nr_cpu_ids()); 82 + 83 + // Ensure the `id` fits in an [`i32`] as it's also representable that way. 84 + debug_assert!(id <= i32::MAX as u32); 85 + 86 + // INVARIANT: The function safety guarantees `id` is a valid CPU id. 87 + Self(id) 88 + } 89 + 90 + /// Creates a new [`CpuId`] from the given `id`, checking that it is valid. 91 + pub fn from_u32(id: u32) -> Option<Self> { 92 + if id >= nr_cpu_ids() { 93 + None 94 + } else { 95 + // INVARIANT: `id` has just been checked as a valid CPU ID. 96 + Some(Self(id)) 97 + } 98 + } 99 + 100 + /// Returns CPU number. 101 + #[inline] 102 + pub fn as_u32(&self) -> u32 { 103 + self.0 104 + } 105 + } 106 + 107 + impl From<CpuId> for u32 { 108 + fn from(id: CpuId) -> Self { 109 + id.as_u32() 110 + } 111 + } 112 + 113 + impl From<CpuId> for i32 { 114 + fn from(id: CpuId) -> Self { 115 + id.as_u32() as i32 116 + } 117 + } 118 + 9 119 /// Creates a new instance of CPU's device. 10 120 /// 11 121 /// # Safety