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    /// Initializes a new `RawBrwLockPi` in-place.
65    ///
66    /// # Safety
67    ///
68    /// The caller must ensure that `class_id` is either null or points to a valid,
69    /// static `LockClassId` that remains valid for the lifetime of the lock.
70    #[inline]
71    pub unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
72        zr::pin_init_ffi!(cpp_brwlock_pi_init, class_id)
73    }
74
75    /// Returns a raw pointer to the underlying storage.
76    #[inline]
77    pub fn as_mut_ptr(&self) -> *mut c_void {
78        self as *const Self as *mut Self as *mut c_void
79    }
80
81    /// Acquires the lock in shared (read) mode.
82    ///
83    /// # Safety
84    ///
85    /// The caller must ensure that the lock is pinned and initialized. If `lock_dep` is enabled,
86    /// `entry` must point to valid storage for a lockdep entry.
87    #[inline]
88    pub unsafe fn acquire_read(&self, entry: *mut c_void) {
89        // SAFETY: The FFI call is safe because the lock is initialized, and the caller guarantees
90        // that `entry` (if applicable) are valid.
91        unsafe {
92            cpp_brwlock_pi_acquire_read(self.as_mut_ptr(), entry);
93        }
94    }
95
96    /// Releases the lock from shared (read) mode.
97    ///
98    /// # Safety
99    ///
100    /// The caller must currently hold the read lock on this instance. If `lock_dep` is enabled,
101    /// `entry` must point to the same valid storage used during acquisition.
102    #[inline]
103    pub unsafe fn release_read(&self, entry: *mut c_void) {
104        // SAFETY: The FFI call is safe because the lock is initialized and the caller currently
105        // holds the read lock.
106        unsafe {
107            cpp_brwlock_pi_release_read(self.as_mut_ptr(), entry);
108        }
109    }
110
111    /// Acquires the lock in exclusive (write) mode.
112    ///
113    /// # Safety
114    ///
115    /// The caller must ensure that the lock is pinned and initialized. If `lock_dep` is enabled,
116    /// `entry` must point to valid storage for a lockdep entry.
117    #[inline]
118    pub unsafe fn acquire_write(&self, entry: *mut c_void) {
119        // SAFETY: The FFI call is safe because the lock is initialized, and the caller guarantees
120        // that `entry` (if applicable) are valid.
121        unsafe {
122            cpp_brwlock_pi_acquire_write(self.as_mut_ptr(), entry);
123        }
124    }
125
126    /// Releases the lock from exclusive (write) mode.
127    ///
128    /// # Safety
129    ///
130    /// The caller must currently hold the write lock on this instance. If `lock_dep` is enabled,
131    /// `entry` must point to the same valid storage used during acquisition.
132    #[inline]
133    pub unsafe fn release_write(&self, entry: *mut c_void) {
134        // SAFETY: The FFI call is safe because the lock is initialized and the caller currently
135        // holds the write lock.
136        unsafe {
137            cpp_brwlock_pi_release_write(self.as_mut_ptr(), entry);
138        }
139    }
140}
141
142#[cfg(all(not(target_arch = "riscv64"), not(feature = "lock_dep")))]
143const _: () = {
144    assert!(core::mem::size_of::<RawBrwLockPi>() == 128);
145    assert!(core::mem::align_of::<RawBrwLockPi>() == 16);
146};
147
148#[cfg(all(not(target_arch = "riscv64"), feature = "lock_dep"))]
149const _: () = {
150    assert!(core::mem::size_of::<RawBrwLockPi>() == 144);
151    assert!(core::mem::align_of::<RawBrwLockPi>() == 16);
152};
153
154#[cfg(all(target_arch = "riscv64", not(feature = "lock_dep")))]
155const _: () = {
156    assert!(core::mem::size_of::<RawBrwLockPi>() == 72);
157    assert!(core::mem::align_of::<RawBrwLockPi>() == 8);
158};
159
160#[cfg(all(target_arch = "riscv64", feature = "lock_dep"))]
161const _: () = {
162    assert!(core::mem::size_of::<RawBrwLockPi>() == 80);
163    assert!(core::mem::align_of::<RawBrwLockPi>() == 8);
164};