blob: a880ec3b8538a73a4b41b10bbe9e3b526739b72e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
// 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
}
}
|