diff options
Diffstat (limited to 'rust/kernel/sync/lock.rs')
| -rw-r--r-- | rust/kernel/sync/lock.rs | 35 | 
1 files changed, 34 insertions, 1 deletions
| diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index 41dcddac69e2..eb80048e0110 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -90,12 +90,20 @@ pub unsafe trait Backend {          // SAFETY: The safety requirements ensure that the lock is initialised.          *guard_state = unsafe { Self::lock(ptr) };      } + +    /// Asserts that the lock is held using lockdep. +    /// +    /// # Safety +    /// +    /// Callers must ensure that [`Backend::init`] has been previously called. +    unsafe fn assert_is_held(ptr: *mut Self::State);  }  /// A mutual exclusion primitive.  ///  /// Exposes one of the kernel locking primitives. Which one is exposed depends on the lock  /// [`Backend`] specified as the generic parameter `B`. +#[repr(C)]  #[pin_data]  pub struct Lock<T: ?Sized, B: Backend> {      /// The kernel lock object. @@ -134,6 +142,28 @@ impl<T, B: Backend> Lock<T, B> {      }  } +impl<B: Backend> Lock<(), B> { +    /// Constructs a [`Lock`] from a raw pointer. +    /// +    /// This can be useful for interacting with a lock which was initialised outside of Rust. +    /// +    /// # Safety +    /// +    /// The caller promises that `ptr` points to a valid initialised instance of [`State`] during +    /// the whole lifetime of `'a`. +    /// +    /// [`State`]: Backend::State +    pub unsafe fn from_raw<'a>(ptr: *mut B::State) -> &'a Self { +        // SAFETY: +        // - By the safety contract `ptr` must point to a valid initialised instance of `B::State` +        // - Since the lock data type is `()` which is a ZST, `state` is the only non-ZST member of +        //   the struct +        // - Combined with `#[repr(C)]`, this guarantees `Self` has an equivalent data layout to +        //   `B::State`. +        unsafe { &*ptr.cast() } +    } +} +  impl<T: ?Sized, B: Backend> Lock<T, B> {      /// Acquires the lock and gives the caller access to the data protected by it.      pub fn lock(&self) -> Guard<'_, T, B> { @@ -211,7 +241,10 @@ impl<'a, T: ?Sized, B: Backend> Guard<'a, T, B> {      /// # Safety      ///      /// The caller must ensure that it owns the lock. -    pub(crate) unsafe fn new(lock: &'a Lock<T, B>, state: B::GuardState) -> Self { +    pub unsafe fn new(lock: &'a Lock<T, B>, state: B::GuardState) -> Self { +        // SAFETY: The caller can only hold the lock if `Backend::init` has already been called. +        unsafe { B::assert_is_held(lock.state.get()) }; +          Self {              lock,              state, | 
