89 lines · 3.8 KB · Rust
RawDownload
// SPDX-License-Identifier: GPL-2.0 //! Interrupt controls//!//! This module allows Rust code to annotate areas of code where local processor interrupts should//! be disabled, along with actually disabling local processor interrupts.//!//! # ⚠️ Warning! ⚠️//!//! The usage of this module can be more complicated than meets the eye, especially surrounding//! [preemptible kernels]. It's recommended to take care when using the functions and types defined//! here and familiarize yourself with the various documentation we have before using them, along//! with the various documents we link to here.//!//! # Reading material//!//! - [Software interrupts and realtime (LWN)](https://lwn.net/Articles/520076)//!//! [preemptible kernels]: https://www.kernel.org/doc/html/latest/locking/preempt-locking.html use crate::types::NotThreadSafe; /// A guard that represents local processor interrupt disablement on preemptible kernels.////// [`LocalInterruptDisabled`] is a guard type that represents that local processor interrupts have/// been disabled on a preemptible kernel.////// Certain functions take an immutable reference of [`LocalInterruptDisabled`] in order to require/// that they may only be run in local-interrupt-disabled contexts on preemptible kernels.////// This is a marker type; it has no size, and is simply used as a compile-time guarantee that local/// processor interrupts are disabled on preemptible kernels. Note that no guarantees about the/// state of interrupts are made by this type on non-preemptible kernels.////// # Invariants////// Local processor interrupts are disabled on preemptible kernels for as long as an object of this/// type exists.pub struct LocalInterruptDisabled(NotThreadSafe); /// Disable local processor interrupts on a preemptible kernel.////// This function disables local processor interrupts on a preemptible kernel, and returns a/// [`LocalInterruptDisabled`] token as proof of this. On non-preemptible kernels, this function is/// a no-op.////// **Usage of this function is discouraged** unless you are absolutely sure you know what you are/// doing, as kernel interfaces for Rust that deal with interrupt state will typically handle local/// processor interrupt state management on their own and managing this by hand is quite error/// prone.#[inline]pub fn local_interrupt_disable() -> LocalInterruptDisabled {    // SAFETY: It's always safe to call `local_interrupt_disable()`.    unsafe { bindings::local_interrupt_disable() };     LocalInterruptDisabled(NotThreadSafe)} impl Drop for LocalInterruptDisabled {    #[inline]    fn drop(&mut self) {        // SAFETY: Per type invariants, a `local_interrupt_disable()` must be called to create this        // object, hence calling the corresponding `local_interrupt_enable()` is safe.        unsafe { bindings::local_interrupt_enable() };    }} impl LocalInterruptDisabled {    /// Assume that local processor interrupts are disabled on preemptible kernels.    ///    /// This can be used for annotating code that is known to be run in contexts where local    /// processor interrupts are disabled on preemptible kernels. It makes no changes to the local    /// interrupt state on its own.    ///    /// # Safety    ///    /// For the whole life `'a`, local interrupts must be disabled on preemptible kernels. This    /// could be a context like, for example, an interrupt handler.    #[inline]    pub unsafe fn assume_disabled<'a>() -> &'a LocalInterruptDisabled {        const ASSUME_DISABLED: &LocalInterruptDisabled = &LocalInterruptDisabled(NotThreadSafe);         // Confirm they're actually disabled if lockdep is available        // SAFETY: It's always safe to call `lockdep_assert_irqs_disabled()`.        unsafe { bindings::lockdep_assert_irqs_disabled() };         ASSUME_DISABLED    }}