mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 15:03:53 +02:00
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>
This commit is contained in:
parent
4823a58093
commit
ebf2e500e0
|
@ -6,6 +6,116 @@
|
|||
|
||||
use crate::{bindings, 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
|
||||
}
|
||||
}
|
||||
|
||||
/// The CPU ID.
|
||||
///
|
||||
/// Represents a CPU identifier as a wrapper around an [`u32`].
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// The CPU ID lies within the range `[0, nr_cpu_ids())`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use kernel::cpu::CpuId;
|
||||
///
|
||||
/// let cpu = 0;
|
||||
///
|
||||
/// // SAFETY: 0 is always a valid CPU number.
|
||||
/// let id = unsafe { CpuId::from_u32_unchecked(cpu) };
|
||||
///
|
||||
/// assert_eq!(id.as_u32(), cpu);
|
||||
/// assert!(CpuId::from_i32(0).is_some());
|
||||
/// assert!(CpuId::from_i32(-1).is_none());
|
||||
/// ```
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct CpuId(u32);
|
||||
|
||||
impl CpuId {
|
||||
/// Creates a new [`CpuId`] from the given `id` without checking bounds.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`).
|
||||
#[inline]
|
||||
pub unsafe fn from_i32_unchecked(id: i32) -> Self {
|
||||
debug_assert!(id >= 0);
|
||||
debug_assert!((id as u32) < nr_cpu_ids());
|
||||
|
||||
// INVARIANT: The function safety guarantees `id` is a valid CPU id.
|
||||
Self(id as u32)
|
||||
}
|
||||
|
||||
/// Creates a new [`CpuId`] from the given `id`, checking that it is valid.
|
||||
pub fn from_i32(id: i32) -> Option<Self> {
|
||||
if id < 0 || id as u32 >= nr_cpu_ids() {
|
||||
None
|
||||
} else {
|
||||
// INVARIANT: `id` has just been checked as a valid CPU ID.
|
||||
Some(Self(id as u32))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new [`CpuId`] from the given `id` without checking bounds.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`).
|
||||
#[inline]
|
||||
pub unsafe fn from_u32_unchecked(id: u32) -> Self {
|
||||
debug_assert!(id < nr_cpu_ids());
|
||||
|
||||
// Ensure the `id` fits in an [`i32`] as it's also representable that way.
|
||||
debug_assert!(id <= i32::MAX as u32);
|
||||
|
||||
// INVARIANT: The function safety guarantees `id` is a valid CPU id.
|
||||
Self(id)
|
||||
}
|
||||
|
||||
/// Creates a new [`CpuId`] from the given `id`, checking that it is valid.
|
||||
pub fn from_u32(id: u32) -> Option<Self> {
|
||||
if id >= nr_cpu_ids() {
|
||||
None
|
||||
} else {
|
||||
// INVARIANT: `id` has just been checked as a valid CPU ID.
|
||||
Some(Self(id))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns CPU number.
|
||||
#[inline]
|
||||
pub fn as_u32(&self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CpuId> for u32 {
|
||||
fn from(id: CpuId) -> Self {
|
||||
id.as_u32()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CpuId> for i32 {
|
||||
fn from(id: CpuId) -> Self {
|
||||
id.as_u32() as i32
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new instance of CPU's device.
|
||||
///
|
||||
/// # Safety
|
||||
|
|
Loading…
Reference in New Issue
Block a user