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 core::ffi::c_void;
6use core::pin::Pin;
7use pin_init::{PinInit, pin_data, pinned_drop};
8
9unsafe extern "C" {
10    fn cpp_brwlock_pi_init(lock: *mut c_void, class_id: *const c_void);
11    fn cpp_brwlock_pi_destroy(lock: *mut c_void);
12    fn cpp_brwlock_pi_acquire_read(lock: *mut c_void, entry_storage: *mut c_void);
13    fn cpp_brwlock_pi_release_read(lock: *mut c_void, entry_storage: *mut c_void);
14    fn cpp_brwlock_pi_acquire_write(lock: *mut c_void, entry_storage: *mut c_void);
15    fn cpp_brwlock_pi_release_write(lock: *mut c_void, entry_storage: *mut c_void);
16}
17
18#[cfg(not(target_arch = "riscv64"))]
19#[repr(C, align(16))]
20struct RawBrwLockPiStorage(zr::OpaqueBytes<128>);
21
22#[cfg(target_arch = "riscv64")]
23#[repr(C, align(8))]
24struct RawBrwLockPiStorage(zr::OpaqueBytes<72>);
25
26/// Opaque layout block matching the Zircon C++ BrwLockPi exactly.
27#[cfg(not(target_arch = "riscv64"))]
28#[pin_data(PinnedDrop)]
29#[repr(C, align(16))]
30pub struct RawBrwLockPi {
31    #[cfg(feature = "lock_dep")]
32    class_id: *const c_void,
33    storage: RawBrwLockPiStorage,
34}
35
36#[cfg(target_arch = "riscv64")]
37#[pin_data(PinnedDrop)]
38#[repr(C, align(8))]
39pub struct RawBrwLockPi {
40    #[cfg(feature = "lock_dep")]
41    class_id: *const c_void,
42    storage: RawBrwLockPiStorage,
43}
44
45// SAFETY: RawBrwLockPi is safe to share and access across threads because it delegates
46// to the thread-safe Zircon kernel BrwLockPi implementation.
47unsafe impl Sync for RawBrwLockPi {}
48unsafe impl Send for RawBrwLockPi {}
49
50#[pinned_drop]
51impl PinnedDrop for RawBrwLockPi {
52    fn drop(self: Pin<&mut Self>) {
53        // SAFETY: `me.as_mut_ptr()` returns a valid pointer to the pinned C++ object,
54        // and `cpp_brwlock_pi_destroy` is safe to call on a valid initialized object
55        // before its memory is reclaimed.
56        unsafe {
57            let me = self.get_unchecked_mut();
58            cpp_brwlock_pi_destroy(me.as_mut_ptr());
59        }
60    }
61}
62
63impl RawBrwLockPi {
64    pub const LOCK_FLAGS: lockdep::LockFlags = lockdep::LOCK_FLAGS_NONE;
65
66    /// Initializes a new `RawBrwLockPi` in-place.
67    ///
68    /// # Safety
69    ///
70    /// The caller must ensure that `class_id` is either null or points to a valid,
71    /// static `LockClassId` that remains valid for the lifetime of the lock.
72    #[inline]
73    pub unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
74        zr::pin_init_ffi!(cpp_brwlock_pi_init, class_id)
75    }
76
77    /// Returns a raw pointer to the underlying storage.
78    #[inline]
79    pub fn as_mut_ptr(&self) -> *mut c_void {
80        self as *const Self as *mut Self as *mut c_void
81    }
82
83    /// Acquires the lock in shared (read) mode.
84    ///
85    /// # Safety
86    ///
87    /// The caller must ensure that the lock is pinned and initialized. If `lock_dep` is enabled,
88    /// `entry` must point to valid storage for a lockdep entry.
89    #[inline]
90    pub unsafe fn acquire_read(&self, entry: *mut c_void) {
91        // SAFETY: The FFI call is safe because the lock is initialized, and the caller guarantees
92        // that `entry` (if applicable) are valid.
93        unsafe {
94            cpp_brwlock_pi_acquire_read(self.as_mut_ptr(), entry);
95        }
96    }
97
98    /// Releases the lock from shared (read) mode.
99    ///
100    /// # Safety
101    ///
102    /// The caller must currently hold the read lock on this instance. If `lock_dep` is enabled,
103    /// `entry` must point to the same valid storage used during acquisition.
104    #[inline]
105    pub unsafe fn release_read(&self, entry: *mut c_void) {
106        // SAFETY: The FFI call is safe because the lock is initialized and the caller currently
107        // holds the read lock.
108        unsafe {
109            cpp_brwlock_pi_release_read(self.as_mut_ptr(), entry);
110        }
111    }
112
113    /// Acquires the lock in exclusive (write) mode.
114    ///
115    /// # Safety
116    ///
117    /// The caller must ensure that the lock is pinned and initialized. If `lock_dep` is enabled,
118    /// `entry` must point to valid storage for a lockdep entry.
119    #[inline]
120    pub unsafe fn acquire_write(&self, entry: *mut c_void) {
121        // SAFETY: The FFI call is safe because the lock is initialized, and the caller guarantees
122        // that `entry` (if applicable) are valid.
123        unsafe {
124            cpp_brwlock_pi_acquire_write(self.as_mut_ptr(), entry);
125        }
126    }
127
128    /// Releases the lock from exclusive (write) mode.
129    ///
130    /// # Safety
131    ///
132    /// The caller must currently hold the write lock on this instance. If `lock_dep` is enabled,
133    /// `entry` must point to the same valid storage used during acquisition.
134    #[inline]
135    pub unsafe fn release_write(&self, entry: *mut c_void) {
136        // SAFETY: The FFI call is safe because the lock is initialized and the caller currently
137        // holds the write lock.
138        unsafe {
139            cpp_brwlock_pi_release_write(self.as_mut_ptr(), entry);
140        }
141    }
142}
143
144#[cfg(all(not(target_arch = "riscv64"), not(feature = "lock_dep")))]
145const _: () = {
146    assert!(core::mem::size_of::<RawBrwLockPi>() == 128);
147    assert!(core::mem::align_of::<RawBrwLockPi>() == 16);
148};
149
150#[cfg(all(not(target_arch = "riscv64"), feature = "lock_dep"))]
151const _: () = {
152    assert!(core::mem::size_of::<RawBrwLockPi>() == 144);
153    assert!(core::mem::align_of::<RawBrwLockPi>() == 16);
154};
155
156#[cfg(all(target_arch = "riscv64", not(feature = "lock_dep")))]
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", feature = "lock_dep"))]
163const _: () = {
164    assert!(core::mem::size_of::<RawBrwLockPi>() == 80);
165    assert!(core::mem::align_of::<RawBrwLockPi>() == 8);
166};