// SPDX-License-Identifier: GPL-2.0

//! Generic CPU definitions.
//!
//! C header: [`include/linux/cpu.h`](srctree/include/linux/cpu.h)

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
    }

    /// Returns the ID of the CPU the code is currently running on.
    ///
    /// The returned value is considered unstable because it may change
    /// unexpectedly due to preemption or CPU migration. It should only be
    /// used when the context ensures that the task remains on the same CPU
    /// or the users could use a stale (yet valid) CPU ID.
    #[inline]
    pub fn current() -> Self {
        // SAFETY: raw_smp_processor_id() always returns a valid CPU ID.
        unsafe { Self::from_u32_unchecked(bindings::raw_smp_processor_id()) }
    }
}

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
///
/// Reference counting is not implemented for the CPU device in the C code. When a CPU is
/// hot-unplugged, the corresponding CPU device is unregistered, but its associated memory
/// is not freed.
///
/// Callers must ensure that the CPU device is not used after it has been unregistered.
/// This can be achieved, for example, by registering a CPU hotplug notifier and removing
/// any references to the CPU device within the notifier's callback.
pub unsafe fn from_cpu(cpu: CpuId) -> Result<&'static Device> {
    // SAFETY: It is safe to call `get_cpu_device()` for any CPU.
    let ptr = unsafe { bindings::get_cpu_device(u32::from(cpu)) };
    if ptr.is_null() {
        return Err(ENODEV);
    }

    // SAFETY: The pointer returned by `get_cpu_device()`, if not `NULL`, is a valid pointer to
    // a `struct device` and is never freed by the C code.
    Ok(unsafe { Device::from_raw(ptr) })
}
