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}