Skip to main content

ksync/
raw_lock.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 core::ffi::c_void;
6use pin_init::PinInit;
7
8/// Trait defining a policy for how a lock should be acquired and released. A given `RawLock` may
9/// have multiple policy implementations allowing a specific instance of a lock to be acquired, at
10/// different times, in different ways.
11///
12/// # Safety
13///
14/// Implementors must guarantee that:
15/// 1. [`acquire`](Self::acquire) and [`reacquire`](Self::reacquire) establish synchronization
16///    (shared or exclusive mutual exclusion) on `lock` until the matching
17///    [`release`](Self::release) call completes.
18/// 2. The split sequences ([`pre_validate`](Self::pre_validate) followed by
19///    [`post_validate_acquire`](Self::post_validate_acquire), and
20///    [`pre_reacquire`](Self::pre_reacquire) followed by
21///    [`post_validate_reacquire`](Self::post_validate_reacquire)) establish the exact same
22///    synchronization guarantees as [`acquire`](Self::acquire) and
23///    [`reacquire`](Self::reacquire), respectively.
24pub unsafe trait LockPolicy<L: RawLock> {
25    /// Arguments passed when acquiring the lock under this policy.
26    type AcquireArgs: Copy;
27
28    /// State stored in the pinned guard across lock acquisition and release.
29    type GuardState: Default;
30
31    /// Performs any pre-validation setup (such as disabling and saving interrupts) before
32    /// lockdep validation runs.
33    ///
34    /// # Safety
35    ///
36    /// Any state changes made by `pre_validate` (such as disabling interrupts) must be paired with
37    /// a subsequent [`post_validate_acquire`](Self::post_validate_acquire) and
38    /// [`release`](Self::release) on the same thread.
39    #[inline]
40    unsafe fn pre_validate(_lock: &L, _state: &mut Self::GuardState, _args: Self::AcquireArgs) {}
41
42    /// Re-runs pre-validation on an existing `GuardState` before re-acquiring the lock (e.g. in
43    /// `call_unlocked`).
44    ///
45    /// # Safety
46    ///
47    /// Same safety requirements as [`pre_validate`](Self::pre_validate).
48    #[inline]
49    unsafe fn pre_reacquire(_lock: &L, _state: &mut Self::GuardState) {}
50
51    /// Acquires the raw synchronization lock.
52    ///
53    /// # Safety
54    ///
55    /// 1. `state` must reference a valid, exclusive, stack-pinned `GuardState` slot initialized
56    ///    with `Self::GuardState::default()`.
57    /// 2. The caller must ensure that `state` remains pinned on the stack and is not dropped or
58    ///    moved until the matching [`release`](Self::release) call completes.
59    unsafe fn acquire(lock: &L, state: &mut Self::GuardState, args: Self::AcquireArgs);
60
61    /// Acquires the raw synchronization lock after [`pre_validate`](Self::pre_validate) and
62    /// lockdep validation have completed.
63    ///
64    /// # Safety
65    ///
66    /// Same safety requirements as [`acquire`](Self::acquire), after
67    /// [`pre_validate`](Self::pre_validate) has run on `state`.
68    #[inline]
69    unsafe fn post_validate_acquire(
70        lock: &L,
71        state: &mut Self::GuardState,
72        args: Self::AcquireArgs,
73    ) {
74        // SAFETY: Caller upholds the `LockPolicy::acquire` contract.
75        unsafe {
76            Self::acquire(lock, state, args);
77        }
78    }
79
80    /// Re-acquires the raw synchronization lock using existing guard state (e.g. after
81    /// `call_unlocked`).
82    ///
83    /// # Safety
84    ///
85    /// Same safety requirements as [`acquire`](Self::acquire).
86    unsafe fn reacquire(lock: &L, state: &mut Self::GuardState);
87
88    /// Re-acquires the raw synchronization lock after [`pre_reacquire`](Self::pre_reacquire) and
89    /// lockdep validation have completed.
90    ///
91    /// # Safety
92    ///
93    /// Same safety requirements as [`reacquire`](Self::reacquire), after
94    /// [`pre_reacquire`](Self::pre_reacquire) has run on `state`.
95    #[inline]
96    unsafe fn post_validate_reacquire(lock: &L, state: &mut Self::GuardState) {
97        // SAFETY: Caller upholds the `LockPolicy::reacquire` contract.
98        unsafe {
99            Self::reacquire(lock, state);
100        }
101    }
102
103    /// Temporarily untracks the held lock in lockdep (used by `call_untracked`).
104    ///
105    /// # Safety
106    ///
107    /// `state` must be the active `GuardState` initialized by [`acquire`](Self::acquire) for a
108    /// lock currently held by the calling thread, and must be paired with a matching
109    /// [`retrack`](Self::retrack) call before the lock is released.
110    #[inline]
111    unsafe fn untrack(_lock: &L, _state: &mut Self::GuardState) {}
112
113    /// Re-tracks the held lock in lockdep after [`untrack`](Self::untrack) (used by
114    /// `call_untracked`).
115    ///
116    /// # Safety
117    ///
118    /// Must be called on the same `state` after a preceding [`untrack`](Self::untrack) call while
119    /// the lock remains held by the calling thread.
120    #[inline]
121    unsafe fn retrack(_lock: &L, _state: &mut Self::GuardState) {}
122
123    /// Releases the raw synchronization lock, restoring the state.
124    ///
125    /// # Safety
126    ///
127    /// 1. `state` must reference the exact same pinned stack slot passed to the corresponding
128    ///    [`acquire`](Self::acquire) call.
129    /// 2. The caller must guarantee that the current thread actually holds this lock (i.e. we are
130    ///    releasing a lock we currently own).
131    unsafe fn release(lock: &L, state: &mut Self::GuardState);
132}
133
134/// Marker subtrait for [`LockPolicy`] implementations that enforce exclusive mutual exclusion.
135///
136/// # Safety
137///
138/// In addition to [`LockPolicy`], implementors must guarantee exclusive mutual exclusion
139/// (at most one thread may hold the lock at a time) between acquisition and
140/// [`release`](LockPolicy::release).
141pub unsafe trait ExclusiveLockPolicy<L: RawLock>: LockPolicy<L> {}
142
143/// Trait defining a raw, un-instrumented synchronization lock abstraction.
144///
145/// Implementors of `RawLock` supply the platform-specific lock storage, in-place pinning
146/// initialization logic, and raw synchronization entry points.
147///
148/// # Safety
149///
150/// Implementors must represent a physical synchronization primitive with non-zero size whose
151/// [`as_mut_ptr`](Self::as_mut_ptr) uniquely identifies the underlying lock storage for the
152/// lifetime of `&self`.
153pub unsafe trait RawLock: Sized {
154    /// Default policy that should be used when acquiring this lock.
155    type DefaultPolicy: ExclusiveLockPolicy<Self>;
156
157    /// Returns a PinInit block to initialize the raw lock in-place.
158    ///
159    /// # Safety
160    ///
161    /// The caller must ensure that `class_id` is either null or points to a valid,
162    /// static `LockClassId` that remains valid for the lifetime of the lock.
163    unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible>;
164
165    /// Convert the raw lock reference to a standard c_void pointer for FFI.
166    fn as_mut_ptr(&self) -> *mut c_void;
167}
168
169/// Trait for [`RawLock`] types that can be statically initialized in a `const` context (e.g. for
170/// global singleton locks).
171pub trait ConstRawLock: RawLock {
172    /// Constant-initialized value for the lock.
173    #[allow(clippy::declare_interior_mutable_const)]
174    const INIT: Self;
175}