Skip to main content

ksync/
raw_kernel_brwlock.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::lockdep_tracked::LockdepTracked;
6use crate::raw_lock::{ExclusiveLockPolicy, LockPolicy, RawLock};
7use core::ffi::c_void;
8use pin_init::{PinInit, pin_data};
9
10unsafe extern "C" {
11    fn cpp_brwlock_pi_init(lock: *mut c_void, class_id: *const c_void);
12    fn cpp_brwlock_pi_destroy(lock: *mut c_void);
13    fn cpp_brwlock_pi_acquire_read(lock: *mut c_void);
14    fn cpp_brwlock_pi_release_read(lock: *mut c_void);
15    fn cpp_brwlock_pi_acquire_write(lock: *mut c_void);
16    fn cpp_brwlock_pi_release_write(lock: *mut c_void);
17}
18
19/// Opaque layout block matching the Zircon C++ `BrwLockPi` object.
20#[cfg(not(target_arch = "riscv64"))]
21#[pin_data(PinnedDrop)]
22#[repr(C, align(16))]
23pub struct RawBrwLockPiStorage {
24    storage: zr::OpaqueBytes<128>,
25}
26
27/// Opaque layout block matching the Zircon C++ `BrwLockPi` object.
28#[cfg(target_arch = "riscv64")]
29#[pin_data(PinnedDrop)]
30#[repr(C, align(8))]
31pub struct RawBrwLockPiStorage {
32    storage: zr::OpaqueBytes<72>,
33}
34
35// SAFETY: `RawBrwLockPiStorage` is safe to share and access across threads because it delegates
36// to the thread-safe Zircon kernel `BrwLockPi` implementation.
37unsafe impl Sync for RawBrwLockPiStorage {}
38// SAFETY: `RawBrwLockPiStorage` is safe to send across threads because it delegates to the
39// thread-safe Zircon kernel `BrwLockPi` implementation.
40unsafe impl Send for RawBrwLockPiStorage {}
41
42zr::unsafe_pinned_drop_ffi!(RawBrwLockPiStorage, cpp_brwlock_pi_destroy);
43
44/// Policy for acquiring and releasing a `RawBrwLockPiStorage` in shared (read) mode.
45pub struct RawBrwLockPiReadPolicy;
46
47// SAFETY: `cpp_brwlock_pi_acquire_read` and `cpp_brwlock_pi_release_read` enforce shared reader
48// synchronization on `RawBrwLockPiStorage`.
49unsafe impl LockPolicy<RawBrwLockPiStorage> for RawBrwLockPiReadPolicy {
50    type AcquireArgs = ();
51    type GuardState = ();
52
53    #[inline]
54    unsafe fn acquire(lock: &RawBrwLockPiStorage, _state: &mut Self::GuardState, _args: ()) {
55        // SAFETY: The FFI call is safe because the lock is initialized.
56        unsafe {
57            cpp_brwlock_pi_acquire_read(lock.as_mut_ptr());
58        }
59    }
60
61    #[inline]
62    unsafe fn reacquire(lock: &RawBrwLockPiStorage, state: &mut Self::GuardState) {
63        // SAFETY: Caller upholds the `LockPolicy::reacquire` contract.
64        unsafe {
65            Self::acquire(lock, state, ());
66        }
67    }
68
69    #[inline]
70    unsafe fn release(lock: &RawBrwLockPiStorage, _state: &mut Self::GuardState) {
71        // SAFETY: The FFI call is safe because the lock is initialized and the caller currently
72        // holds the read lock.
73        unsafe {
74            cpp_brwlock_pi_release_read(lock.as_mut_ptr());
75        }
76    }
77}
78
79/// Policy for acquiring and releasing a `RawBrwLockPiStorage` in exclusive (write) mode.
80pub struct RawBrwLockPiWritePolicy;
81
82// SAFETY: `cpp_brwlock_pi_acquire_write` and `cpp_brwlock_pi_release_write` enforce exclusive
83// mutual exclusion on `RawBrwLockPiStorage`.
84unsafe impl LockPolicy<RawBrwLockPiStorage> for RawBrwLockPiWritePolicy {
85    type AcquireArgs = ();
86    type GuardState = ();
87
88    #[inline]
89    unsafe fn acquire(lock: &RawBrwLockPiStorage, _state: &mut Self::GuardState, _args: ()) {
90        // SAFETY: The FFI call is safe because the lock is initialized.
91        unsafe {
92            cpp_brwlock_pi_acquire_write(lock.as_mut_ptr());
93        }
94    }
95
96    #[inline]
97    unsafe fn reacquire(lock: &RawBrwLockPiStorage, state: &mut Self::GuardState) {
98        // SAFETY: Caller upholds the `LockPolicy::reacquire` contract.
99        unsafe {
100            Self::acquire(lock, state, ());
101        }
102    }
103
104    #[inline]
105    unsafe fn release(lock: &RawBrwLockPiStorage, _state: &mut Self::GuardState) {
106        // SAFETY: The FFI call is safe because the lock is initialized and the caller currently
107        // holds the write lock.
108        unsafe {
109            cpp_brwlock_pi_release_write(lock.as_mut_ptr());
110        }
111    }
112}
113
114// SAFETY: `RawBrwLockPiWritePolicy` enforces exclusive mutual exclusion on `RawBrwLockPiStorage`.
115unsafe impl ExclusiveLockPolicy<RawBrwLockPiStorage> for RawBrwLockPiWritePolicy {}
116
117// SAFETY: `RawBrwLockPiStorage` is a physical kernel rwlock with a unique storage address.
118unsafe impl RawLock for RawBrwLockPiStorage {
119    type DefaultPolicy = RawBrwLockPiWritePolicy;
120
121    #[inline]
122    unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
123        zr::pin_init_ffi!(cpp_brwlock_pi_init, class_id)
124    }
125
126    #[inline]
127    fn as_mut_ptr(&self) -> *mut c_void {
128        self as *const Self as *mut Self as *mut c_void
129    }
130}
131
132/// Lockdep-tracked kernel `BrwLockPi` matching the Zircon C++ `Lock<BrwLockPi>` layout.
133pub type RawBrwLockPi = LockdepTracked<RawBrwLockPiStorage>;
134
135#[cfg(all(
136    not(target_arch = "riscv64"),
137    not(any(feature = "lock_dep", feature = "lock_metadata_only"))
138))]
139const _: () = {
140    assert!(core::mem::size_of::<RawBrwLockPi>() == 128);
141    assert!(core::mem::align_of::<RawBrwLockPi>() == 16);
142};
143
144#[cfg(all(
145    not(target_arch = "riscv64"),
146    any(feature = "lock_dep", feature = "lock_metadata_only")
147))]
148const _: () = {
149    assert!(core::mem::size_of::<RawBrwLockPi>() == 144);
150    assert!(core::mem::align_of::<RawBrwLockPi>() == 16);
151};
152
153#[cfg(all(
154    target_arch = "riscv64",
155    not(any(feature = "lock_dep", feature = "lock_metadata_only"))
156))]
157const _: () = {
158    assert!(core::mem::size_of::<RawBrwLockPi>() == 72);
159    assert!(core::mem::align_of::<RawBrwLockPi>() == 8);
160};
161
162#[cfg(all(target_arch = "riscv64", any(feature = "lock_dep", feature = "lock_metadata_only")))]
163const _: () = {
164    assert!(core::mem::size_of::<RawBrwLockPi>() == 80);
165    assert!(core::mem::align_of::<RawBrwLockPi>() == 8);
166};