Skip to main content

ksync/
singleton.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
5use crate::{KMutex, RawMutex};
6
7/// A statically initialized global singleton mutex.
8pub type SingletonMutex<Class, M = RawMutex> = KMutex<Class, M>;
9
10/// Declares a singleton mutex.
11///
12/// This macro defines a struct with the given name and visibility, registers it as a singleton
13/// lock with lockdep under the `rust_lock_classes` linker section, and provides accessors
14/// (`Get()`, `get()`, `lock()`, and `lock_policy()`) to a statically initialized `KMutex`.
15///
16/// # Examples
17///
18/// ```rust
19/// ksync::declare_singleton_mutex!(MyGlobalLock);
20///
21/// // Usage:
22/// ksync::lock!(MyGlobalLock::get().lock());
23/// // or
24/// ksync::lock!(MyGlobalLock::lock());
25/// ```
26#[macro_export]
27macro_rules! declare_singleton_mutex {
28    ($($args:tt)*) => {
29        $crate::declare_singleton_lock!($($args)*);
30    };
31}
32
33/// Declares a singleton critical mutex (disables interrupts/preemption while held).
34#[macro_export]
35#[cfg(feature = "kernel")]
36macro_rules! declare_singleton_critical_mutex {
37    ($(#[$meta:meta])* $vis:vis $name:ident) => {
38        $crate::declare_singleton_lock!($(#[$meta])* $vis $name, $crate::RawCriticalMutex);
39    };
40}
41
42/// Declares a singleton spinlock.
43#[macro_export]
44#[cfg(feature = "kernel")]
45macro_rules! declare_singleton_spinlock {
46    ($(#[$meta:meta])* $vis:vis $name:ident) => {
47        $crate::declare_singleton_lock!($(#[$meta])* $vis $name, $crate::RawSpinlock);
48    };
49}
50
51/// Declares a singleton monitored spinlock (integrated with the kernel lockup detector).
52#[macro_export]
53#[cfg(feature = "kernel")]
54macro_rules! declare_singleton_monitored_spinlock {
55    ($(#[$meta:meta])* $vis:vis $name:ident) => {
56        $crate::declare_singleton_lock!($(#[$meta])* $vis $name, $crate::RawMonitoredSpinlock);
57    };
58}
59
60#[cfg(not(feature = "kernel"))]
61#[cfg(test)]
62mod tests {
63    declare_singleton_mutex!(TestSingleton);
64
65    #[test]
66    fn test_singleton_mutex() {
67        let lock1 = TestSingleton::Get();
68        let lock2 = TestSingleton::get();
69        assert!(core::ptr::eq(lock1, lock2));
70
71        {
72            lock!(let _guard = TestSingleton::Get().lock());
73        }
74
75        {
76            lock!(TestSingleton::lock());
77        }
78    }
79}