Skip to main content

ksync/
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#[cfg(test)]
8extern crate self as ksync;
9
10pub use kstring::declare_interned_string;
11pub use ksync_macro::{declare_singleton_lock, guarded};
12pub use pin_init;
13
14/// Locks a mutex.
15///
16/// Usage:
17///   `ksync::lock!(let mut guard = self.lock_mu());`
18///   Locks the mutex and binds a mutable pin to `guard`. Useful when you need to mutate
19///   guarded fields via `guard.as_mut().fields_mut()`.
20///
21///   `ksync::lock!(let guard = self.lock_mu());`
22///   Locks the mutex and binds an immutable pin to `guard`. Useful for read-only access
23///   to guarded fields via `guard.fields()`.
24///
25///   `ksync::lock!(self.lock_mu());`
26///   Locks the mutex and keeps it locked until the end of the scope, without binding the guard.
27#[macro_export]
28macro_rules! lock {
29    (let mut $guard:ident = $lock_init:expr) => {
30        $crate::pin_init::stack_pin_init!(let $guard = $lock_init);
31        let mut $guard = $guard;
32    };
33    (let $guard:ident = $lock_init:expr) => {
34        $crate::pin_init::stack_pin_init!(let $guard = $lock_init);
35    };
36    ($lock_init:expr) => {
37        $crate::pin_init::stack_pin_init!(let _guard = $lock_init);
38    };
39}
40
41/// A static C-string tag identifying the source location (`"file:line"`) where a lock is acquired.
42///
43/// Used with `RawMonitoredSpinlock` to pass critical section names to the kernel lockup detector.
44/// Construct via the [`source_tag!`] macro, which is the Rust equivalent of C++ `SOURCE_TAG`.
45#[repr(transparent)]
46#[derive(Copy, Clone, Debug, PartialEq, Eq)]
47pub struct SourceTag(&'static core::ffi::CStr);
48
49impl SourceTag {
50    /// Creates a `SourceTag` from a static null-terminated byte slice without checking for
51    /// interior null bytes.
52    ///
53    /// # Safety
54    ///
55    /// `bytes` must be a valid null-terminated C string (ending in `\0` with no interior `\0`
56    /// bytes).
57    #[inline]
58    pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &'static [u8]) -> Self {
59        // SAFETY: The caller guarantees `bytes` is a valid null-terminated byte slice.
60        Self(unsafe { core::ffi::CStr::from_bytes_with_nul_unchecked(bytes) })
61    }
62
63    /// Creates a `SourceTag` from a static `CStr`.
64    #[inline]
65    pub const fn from_cstr(cstr: &'static core::ffi::CStr) -> Self {
66        Self(cstr)
67    }
68
69    /// Returns a pointer to the underlying null-terminated C string.
70    #[inline]
71    pub const fn as_ptr(&self) -> *const core::ffi::c_char {
72        self.0.as_ptr()
73    }
74
75    /// Returns the underlying `CStr`.
76    #[inline]
77    pub const fn as_cstr(&self) -> &'static core::ffi::CStr {
78        self.0
79    }
80}
81
82impl Default for SourceTag {
83    #[inline]
84    fn default() -> Self {
85        Self(c"<unknown>")
86    }
87}
88
89/// Expands to a [`SourceTag`] containing the file path and line number (`"file:line"`) of the
90/// call site, equivalent to C++ `SOURCE_TAG`.
91#[macro_export]
92macro_rules! source_tag {
93    () => {{
94        // SAFETY: `concat!(file!(), ":", line!(), "\0")` produces a static string literal ending
95        // in a single NUL byte and containing no interior NUL bytes.
96        const TAG: $crate::SourceTag = unsafe {
97            $crate::SourceTag::from_bytes_with_nul_unchecked(
98                concat!(file!(), ":", line!(), "\0").as_bytes(),
99            )
100        };
101        TAG
102    }};
103}
104
105mod kcell;
106mod kmutex;
107mod konce_cell;
108mod lock_token;
109mod phantom_mutex;
110mod raw_lock;
111mod singleton;
112
113#[cfg(not(feature = "kernel"))]
114mod raw_userspace_mutex;
115
116#[cfg(feature = "kernel")]
117mod raw_kernel_mutex;
118#[cfg(feature = "kernel")]
119mod raw_spin_lock;
120
121pub use kcell::{KCell, KCellInit, kcell_init};
122pub use konce_cell::{KOnceCell, KOnceCellGuard};
123#[cfg(any(feature = "kernel", test))]
124mod brwlock;
125
126#[cfg(feature = "kernel")]
127mod raw_kernel_brwlock;
128
129#[cfg(all(not(feature = "kernel"), test))]
130mod raw_userspace_brwlock;
131
132pub use kmutex::{
133    AliasedLock, KMutex, KMutexAliasedGuard, KMutexGuard, aliased_lock, aliased_lock_policy,
134    aliased_lock_policy_with, aliased_lock_with,
135};
136pub use lock_token::LockToken;
137pub use lockdep::{LOCK_FLAGS_SINGLETON_LOCK, LockClass, LockClassRegistration, LockFlags};
138pub use phantom_mutex::PhantomMutex;
139pub use raw_lock::{LockPolicy, RawLock};
140pub use singleton::SingletonMutex;
141
142#[cfg(not(feature = "kernel"))]
143pub use raw_userspace_mutex::RawMutex;
144
145#[cfg(not(feature = "kernel"))]
146pub type LockEntryStorage = ();
147
148#[cfg(feature = "kernel")]
149pub use raw_spin_lock::{
150    InterruptSavedState, IrqSavePolicy, MonitoredSpinlockGuardState, NoIrqSavePolicy,
151    RawMonitoredSpinlock, RawSpinlock,
152};
153#[cfg(feature = "kernel")]
154pub type KSpinlock<Class> = KMutex<Class, RawSpinlock>;
155#[cfg(feature = "kernel")]
156pub type KMonitoredSpinlock<Class> = KMutex<Class, RawMonitoredSpinlock>;
157#[cfg(any(feature = "kernel", test))]
158pub use brwlock::{BrwLockPi, BrwLockPiReadGuard, BrwLockPiWriteGuard};
159#[cfg(feature = "kernel")]
160pub use raw_kernel_brwlock::RawBrwLockPi;
161#[cfg(feature = "kernel")]
162pub use raw_kernel_mutex::{LockEntryStorage, RawCriticalMutex, RawMutex};
163#[cfg(all(not(feature = "kernel"), test))]
164pub use raw_userspace_brwlock::RawBrwLockPi;