Skip to main content

lockdep/
lib.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#![no_std]
6
7/// Flags to specify which rules to apply to a lock class during validation.
8pub type LockFlags = u16;
9
10/// Apply only common rules that apply to all locks.
11pub const LOCK_FLAGS_NONE: LockFlags = 0;
12/// Apply the irq-safety rules in addition to the common rules for all locks.
13pub const LOCK_FLAGS_IRQ_SAFE: LockFlags = 1 << 0;
14/// Apply the nestable rules in addition to the common rules for all locks.
15pub const LOCK_FLAGS_NESTABLE: LockFlags = 1 << 1;
16/// Apply the multi-acquire rules in additioon to the common rules for all
17/// locks.
18pub const LOCK_FLAGS_MULTI_ACQUIRE: LockFlags = 1 << 2;
19/// Apply the leaf lock rules in addition to the common rules for all locks.
20/// NOTE: Use this flag with caution. See https://fxbug.dev/459856993.
21pub const LOCK_FLAGS_LEAF: LockFlags = 1 << 3;
22/// Do not report validation errors. This flag prevents recursive validation
23/// of locks that are acquired by reporting routines.
24pub const LOCK_FLAGS_REPORTING_DISABLED: LockFlags = 1 << 4;
25/// There is only one member of this locks class.
26pub const LOCK_FLAGS_SINGLETON_LOCK: LockFlags = 1 << 5;
27/// Abort the program with an error if a lock is improperly acquired more
28/// than once in the same context.
29pub const LOCK_FLAGS_RE_ACQUIRE_FATAL: LockFlags = 1 << 6;
30/// Do not add this acquisition to the active list. This may be required for
31/// locks that are used to protect context switching logic.
32pub const LOCK_FLAGS_ACTIVE_LIST_DISABLED: LockFlags = 1 << 7;
33/// Do not track this lock.
34pub const LOCK_FLAGS_TRACKING_DISABLED: LockFlags = 1 << 8;
35
36// Keep dependency alive even when lockdep is disabled to satisfy unused dependency lints.
37use zr as _;
38
39/// Trait implemented by lock class types to expose their dynamic LockClassId pointer.
40pub trait LockClass {
41    const ID: *mut core::ffi::c_void;
42}
43
44#[cfg(any(feature = "lock_dep", feature = "lock_metadata_only"))]
45mod enabled {
46    core::cfg_select! {
47        feature = "lock_dep" => {
48            const LOCK_CLASS_STATE_SIZE: usize = 1608;
49            const LOCK_CLASS_REGISTRATION_SIZE: usize = 1624;
50        }
51        feature = "lock_metadata_only" => {
52            const LOCK_CLASS_STATE_SIZE: usize = 8;
53            const LOCK_CLASS_REGISTRATION_SIZE: usize = 24;
54        }
55    }
56
57    #[repr(C, align(8))]
58    #[derive(Default)]
59    struct LockClassStateStorage(zr::OpaqueBytes<LOCK_CLASS_STATE_SIZE>);
60
61    impl LockClassStateStorage {
62        const fn uninit() -> Self {
63            Self(zr::OpaqueBytes::uninit())
64        }
65    }
66
67    /// A registration entry for a Rust lock class.
68    ///
69    /// This struct is registered with the C++ lockdep implementation via a linker section. The
70    /// layout of this struct is known to C++.
71    #[repr(C)]
72    pub struct LockClassRegistration {
73        name: *const kstring::interned_string::InternedString,
74        flags: u16,
75        state_storage: LockClassStateStorage,
76    }
77
78    unsafe impl Sync for LockClassRegistration {}
79    unsafe impl Send for LockClassRegistration {}
80
81    impl LockClassRegistration {
82        pub const fn new(name: &'static ::kstring::interned_string::InternedString) -> Self {
83            Self { name, flags: 0, state_storage: LockClassStateStorage::uninit() }
84        }
85
86        pub const fn with_flags(
87            name: &'static ::kstring::interned_string::InternedString,
88            flags: u16,
89        ) -> Self {
90            Self { name, flags, state_storage: LockClassStateStorage::uninit() }
91        }
92
93        #[inline]
94        pub const fn get(&self) -> *mut core::ffi::c_void {
95            self.state_storage.0.get() as *mut _
96        }
97    }
98
99    zr::static_assert!(
100        core::mem::size_of::<LockClassRegistration>() == LOCK_CLASS_REGISTRATION_SIZE
101    );
102    zr::static_assert!(core::mem::align_of::<LockClassRegistration>() == 8);
103}
104
105#[cfg(any(feature = "lock_dep", feature = "lock_metadata_only"))]
106pub use enabled::LockClassRegistration;
107
108#[cfg(not(any(feature = "lock_dep", feature = "lock_metadata_only")))]
109mod disabled {
110    /// A registration entry for a Rust lock class (stub for disabled lockdep).
111    pub struct LockClassRegistration;
112
113    impl LockClassRegistration {
114        pub const fn new(_name: &'static ::kstring::interned_string::InternedString) -> Self {
115            Self
116        }
117
118        pub const fn with_flags(
119            _name: &'static ::kstring::interned_string::InternedString,
120            _flags: u16,
121        ) -> Self {
122            Self
123        }
124
125        #[inline]
126        pub const fn get(&self) -> *mut core::ffi::c_void {
127            core::ptr::null_mut()
128        }
129    }
130}
131
132#[cfg(not(any(feature = "lock_dep", feature = "lock_metadata_only")))]
133pub use disabled::LockClassRegistration;