1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Interrupt controls 4 //! 5 //! This module allows Rust code to annotate areas of code where local processor interrupts should 6 //! be disabled, along with actually disabling local processor interrupts. 7 //! 8 //! # ⚠️ Warning! ⚠️ 9 //! 10 //! The usage of this module can be more complicated than meets the eye, especially surrounding 11 //! [preemptible kernels]. It's recommended to take care when using the functions and types defined 12 //! here and familiarize yourself with the various documentation we have before using them, along 13 //! with the various documents we link to here. 14 //! 15 //! # Reading material 16 //! 17 //! - [Software interrupts and realtime (LWN)](https://lwn.net/Articles/520076) 18 //! 19 //! [preemptible kernels]: https://www.kernel.org/doc/html/latest/locking/preempt-locking.html 20 21 use crate::types::NotThreadSafe; 22 23 /// A guard that represents local processor interrupt disablement on preemptible kernels. 24 /// 25 /// [`LocalInterruptDisabled`] is a guard type that represents that local processor interrupts have 26 /// been disabled on a preemptible kernel. 27 /// 28 /// Certain functions take an immutable reference of [`LocalInterruptDisabled`] in order to require 29 /// that they may only be run in local-interrupt-disabled contexts on preemptible kernels. 30 /// 31 /// This is a marker type; it has no size, and is simply used as a compile-time guarantee that local 32 /// processor interrupts are disabled on preemptible kernels. Note that no guarantees about the 33 /// state of interrupts are made by this type on non-preemptible kernels. 34 /// 35 /// # Invariants 36 /// 37 /// Local processor interrupts are disabled on preemptible kernels for as long as an object of this 38 /// type exists. 39 pub struct LocalInterruptDisabled(NotThreadSafe); 40 41 /// Disable local processor interrupts on a preemptible kernel. 42 /// 43 /// This function disables local processor interrupts on a preemptible kernel, and returns a 44 /// [`LocalInterruptDisabled`] token as proof of this. On non-preemptible kernels, this function is 45 /// a no-op. 46 /// 47 /// **Usage of this function is discouraged** unless you are absolutely sure you know what you are 48 /// doing, as kernel interfaces for Rust that deal with interrupt state will typically handle local 49 /// processor interrupt state management on their own and managing this by hand is quite error 50 /// prone. 51 #[inline] 52 pub fn local_interrupt_disable() -> LocalInterruptDisabled { 53 // SAFETY: It's always safe to call `local_interrupt_disable()`. 54 unsafe { bindings::local_interrupt_disable() }; 55 56 LocalInterruptDisabled(NotThreadSafe) 57 } 58 59 impl Drop for LocalInterruptDisabled { 60 #[inline] 61 fn drop(&mut self) { 62 // SAFETY: Per type invariants, a `local_interrupt_disable()` must be called to create this 63 // object, hence calling the corresponding `local_interrupt_enable()` is safe. 64 unsafe { bindings::local_interrupt_enable() }; 65 } 66 } 67 68 impl LocalInterruptDisabled { 69 /// Assume that local processor interrupts are disabled on preemptible kernels. 70 /// 71 /// This can be used for annotating code that is known to be run in contexts where local 72 /// processor interrupts are disabled on preemptible kernels. It makes no changes to the local 73 /// interrupt state on its own. 74 /// 75 /// # Safety 76 /// 77 /// For the whole life `'a`, local interrupts must be disabled on preemptible kernels. This 78 /// could be a context like, for example, an interrupt handler. 79 #[inline] 80 pub unsafe fn assume_disabled<'a>() -> &'a LocalInterruptDisabled { 81 const ASSUME_DISABLED: &LocalInterruptDisabled = &LocalInterruptDisabled(NotThreadSafe); 82 83 // Confirm they're actually disabled if lockdep is available 84 // SAFETY: It's always safe to call `lockdep_assert_irqs_disabled()`. 85 unsafe { bindings::lockdep_assert_irqs_disabled() }; 86 87 ASSUME_DISABLED 88 } 89 } 90