diff --git a/drivers/android/node.rs b/drivers/android/node.rs index fd0c80aba47659..1a46de1e736c85 100644 --- a/drivers/android/node.rs +++ b/drivers/android/node.rs @@ -5,7 +5,7 @@ use kernel::{ io_buffer::IoBufferWriter, linked_list::{GetLinks, Links, List}, prelude::*, - sync::{GuardMut, LockedBy, Mutex, Ref, SpinLock}, + sync::{Guard, LockedBy, Mutex, Ref, SpinLock}, user_ptr::UserSlicePtrWriter, }; @@ -244,7 +244,7 @@ impl Node { pub(crate) fn next_death( &self, - guard: &mut GuardMut<'_, Mutex>, + guard: &mut Guard<'_, Mutex>, ) -> Option> { self.inner.access_mut(guard).death_list.pop_front() } @@ -252,7 +252,7 @@ impl Node { pub(crate) fn add_death( &self, death: Ref, - guard: &mut GuardMut<'_, Mutex>, + guard: &mut Guard<'_, Mutex>, ) { self.inner.access_mut(guard).death_list.push_back(death); } @@ -306,7 +306,7 @@ impl Node { pub(crate) fn populate_counts( &self, out: &mut BinderNodeInfoForRef, - guard: &GuardMut<'_, Mutex>, + guard: &Guard<'_, Mutex>, ) { let inner = self.inner.access(guard); out.strong_count = inner.strong.count as _; @@ -316,7 +316,7 @@ impl Node { pub(crate) fn populate_debug_info( &self, out: &mut BinderNodeDebugInfo, - guard: &GuardMut<'_, Mutex>, + guard: &Guard<'_, Mutex>, ) { out.ptr = self.ptr as _; out.cookie = self.cookie as _; @@ -329,7 +329,7 @@ impl Node { } } - pub(crate) fn force_has_count(&self, guard: &mut GuardMut<'_, Mutex>) { + pub(crate) fn force_has_count(&self, guard: &mut Guard<'_, Mutex>) { let inner = self.inner.access_mut(guard); inner.strong.has_count = true; inner.weak.has_count = true; diff --git a/drivers/android/process.rs b/drivers/android/process.rs index 0cbff1c9c84585..7c7633513183ab 100644 --- a/drivers/android/process.rs +++ b/drivers/android/process.rs @@ -11,7 +11,7 @@ use kernel::{ pages::Pages, prelude::*, rbtree::RBTree, - sync::{GuardMut, Mutex, Ref, RefBorrow, UniqueRef}, + sync::{Guard, Mutex, Ref, RefBorrow, UniqueRef}, task::Task, user_ptr::{UserSlicePtr, UserSlicePtrReader}, }; @@ -949,7 +949,7 @@ impl<'a> Registration<'a> { fn new( process: &'a Process, thread: &'a Ref, - guard: &mut GuardMut<'_, Mutex>, + guard: &mut Guard<'_, Mutex>, ) -> Self { guard.ready_threads.push_back(thread.clone()); Self { process, thread } diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs index e36e73212316d0..32709777bbe5fc 100644 --- a/rust/kernel/sync/condvar.rs +++ b/rust/kernel/sync/condvar.rs @@ -5,7 +5,7 @@ //! This module allows Rust code to use the kernel's [`struct wait_queue_head`] as a condition //! variable. -use super::{GuardMut, Lock, NeedsLockClass}; +use super::{Guard, Lock, NeedsLockClass}; use crate::{bindings, str::CStr, task::Task, Opaque}; use core::{marker::PhantomPinned, pin::Pin}; @@ -61,8 +61,8 @@ impl CondVar { /// /// Returns whether there is a signal pending. #[must_use = "wait returns if a signal is pending, so the caller must check the return value"] - pub fn wait(&self, guard: &mut GuardMut<'_, L>) -> bool { - let lock = guard.guard.lock; + pub fn wait, M>(&self, guard: &mut Guard<'_, L, M>) -> bool { + let lock = guard.lock; let wait = Opaque::::uninit(); // SAFETY: `wait` points to valid memory. @@ -78,12 +78,12 @@ impl CondVar { }; // SAFETY: The guard is evidence that the caller owns the lock. - unsafe { lock.unlock(&mut guard.guard.context) }; + unsafe { lock.unlock(&mut guard.context) }; // SAFETY: No arguments, switches to another thread. unsafe { bindings::schedule() }; - lock.relock(&mut guard.guard.context); + lock.relock(&mut guard.context); // SAFETY: Both `wait` and `wait_list` point to valid memory. unsafe { bindings::finish_wait(self.wait_list.get(), wait.get()) }; diff --git a/rust/kernel/sync/guard.rs b/rust/kernel/sync/guard.rs index 9b0506a31fe773..012bdd19b5ce8c 100644 --- a/rust/kernel/sync/guard.rs +++ b/rust/kernel/sync/guard.rs @@ -14,55 +14,7 @@ use core::pin::Pin; /// when a guard goes out of scope. It also provides a safe and convenient way to access the data /// protected by the lock. #[must_use = "the lock unlocks immediately when the guard is unused"] -pub struct GuardMut<'a, L: Lock + ?Sized> { - pub(crate) guard: Guard<'a, L>, -} - -// SAFETY: `GuardMut` is sync when the data protected by the lock is also sync. This is more -// conservative than the default compiler implementation; more details can be found on -// https://github.com/rust-lang/rust/issues/41622 -- it refers to `MutexGuard` from the standard -// library. -unsafe impl Sync for GuardMut<'_, L> -where - L: Lock + ?Sized, - L::Inner: Sync, -{ -} - -impl core::ops::Deref for GuardMut<'_, L> { - type Target = L::Inner; - - fn deref(&self) -> &Self::Target { - self.guard.deref() - } -} - -impl core::ops::DerefMut for GuardMut<'_, L> { - fn deref_mut(&mut self) -> &mut L::Inner { - // SAFETY: The caller owns the lock, so it is safe to deref the protected data. - unsafe { &mut *self.guard.lock.locked_data().get() } - } -} - -impl<'a, L: Lock + ?Sized> GuardMut<'a, L> { - /// Constructs a new lock guard. - /// - /// # Safety - /// - /// The caller must ensure that it owns the lock. - pub(crate) unsafe fn new(lock: &'a L, context: L::GuardContext) -> Self { - // SAFETY: The safety requirements for this function satisfy the `Guard::new` ones. - Self { - guard: unsafe { Guard::new(lock, context) }, - } - } -} - -/// Allows mutual exclusion primitives that implement the [`Lock`] trait to automatically unlock -/// when a guard goes out of scope. It also provides a safe and convenient way to immutably access -/// the data protected by the lock. -#[must_use = "the lock unlocks immediately when the guard is unused"] -pub struct Guard<'a, L: Lock + ?Sized> { +pub struct Guard<'a, L: Lock + ?Sized, M = WriteLock> { pub(crate) lock: &'a L, pub(crate) context: L::GuardContext, } @@ -71,14 +23,14 @@ pub struct Guard<'a, L: Lock + ?Sized> { // conservative than the default compiler implementation; more details can be found on // https://github.com/rust-lang/rust/issues/41622 -- it refers to `MutexGuard` from the standard // library. -unsafe impl Sync for Guard<'_, L> +unsafe impl Sync for Guard<'_, L, M> where - L: Lock + ?Sized, + L: Lock + ?Sized, L::Inner: Sync, { } -impl core::ops::Deref for Guard<'_, L> { +impl + ?Sized, M> core::ops::Deref for Guard<'_, L, M> { type Target = L::Inner; fn deref(&self) -> &Self::Target { @@ -87,14 +39,21 @@ impl core::ops::Deref for Guard<'_, L> { } } -impl Drop for Guard<'_, L> { +impl + ?Sized> core::ops::DerefMut for Guard<'_, L, WriteLock> { + fn deref_mut(&mut self) -> &mut Self::Target { + // SAFETY: The caller owns the lock, so it is safe to deref the protected data. + unsafe { &mut *self.lock.locked_data().get() } + } +} + +impl + ?Sized, M> Drop for Guard<'_, L, M> { fn drop(&mut self) { // SAFETY: The caller owns the lock, so it is safe to unlock it. unsafe { self.lock.unlock(&mut self.context) }; } } -impl<'a, L: Lock + ?Sized> Guard<'a, L> { +impl<'a, L: Lock + ?Sized, M> Guard<'a, L, M> { /// Constructs a new immutable lock guard. /// /// # Safety @@ -105,16 +64,26 @@ impl<'a, L: Lock + ?Sized> Guard<'a, L> { } } +/// A marker for locks that only allow reading. +pub struct ReadLock; + +/// A marker for locks that allow reading and writing. +pub struct WriteLock; + /// A generic mutual exclusion primitive. /// -/// [`Guard`] and [`GuardMut`] are written such that any mutual exclusion primitive that can -/// implement this trait can also benefit from having an automatic way to unlock itself. +/// [`Guard`] is written such that any mutual exclusion primitive that can implement this trait can +/// also benefit from having an automatic way to unlock itself. /// /// # Safety /// -/// Implementers of this trait must ensure that only one thread/CPU may access the protected data -/// once the lock is held, that is, between calls to `lock_noguard` and `unlock`. -pub unsafe trait Lock { +/// - Implementers of this trait with the [`WriteLock`] marker must ensure that only one thread/CPU +/// may access the protected data once the lock is held, that is, between calls to `lock_noguard` +/// and `unlock`. +/// - Implementers of all other markers must ensure that a mutable reference to the protected data +/// is not active in any thread/CPU because at least one shared refence is active between calls +/// to `lock_noguard` and `unlock`. +pub unsafe trait Lock { /// The type of the data protected by the lock. type Inner: ?Sized; @@ -147,7 +116,7 @@ pub unsafe trait Lock { } /// A generic mutual exclusion primitive that can be instantiated generically. -pub trait CreatableLock: Lock { +pub trait CreatableLock: Lock { /// Constructs a new instance of the lock. /// /// # Safety diff --git a/rust/kernel/sync/locked_by.rs b/rust/kernel/sync/locked_by.rs index e7546e12b8dfff..d3e0b0d5e9b4ec 100644 --- a/rust/kernel/sync/locked_by.rs +++ b/rust/kernel/sync/locked_by.rs @@ -2,7 +2,7 @@ //! A wrapper for data protected by a lock that does not wrap it. -use super::{GuardMut, Lock}; +use super::{Guard, Lock}; use core::{cell::UnsafeCell, ops::Deref, ptr}; /// Allows access to some data to be serialised by a lock that does not wrap it. @@ -77,8 +77,8 @@ impl LockedBy { impl LockedBy { /// Returns a reference to the protected data when the caller provides evidence (via a - /// [`GuardMut`]) that the owner is locked. - pub fn access<'a>(&'a self, guard: &'a GuardMut<'_, L>) -> &'a T { + /// [`Guard`]) that the owner is locked. + pub fn access<'a>(&'a self, guard: &'a Guard<'_, L>) -> &'a T { if !ptr::eq(guard.deref(), self.owner) { panic!("guard does not match owner"); } @@ -88,8 +88,8 @@ impl LockedBy { } /// Returns a mutable reference to the protected data when the caller provides evidence (via a - /// mutable [`GuardMut`]) that the owner is locked mutably. - pub fn access_mut<'a>(&'a self, guard: &'a mut GuardMut<'_, L>) -> &'a mut T { + /// mutable [`Guard`]) that the owner is locked mutably. + pub fn access_mut<'a>(&'a self, guard: &'a mut Guard<'_, L>) -> &'a mut T { if !ptr::eq(guard.deref().deref(), self.owner) { panic!("guard does not match owner"); } diff --git a/rust/kernel/sync/mod.rs b/rust/kernel/sync/mod.rs index 51067fc7b6fc95..dfd4bf4077bebc 100644 --- a/rust/kernel/sync/mod.rs +++ b/rust/kernel/sync/mod.rs @@ -34,7 +34,7 @@ mod spinlock; pub use arc::{Ref, RefBorrow, UniqueRef}; pub use condvar::CondVar; -pub use guard::{CreatableLock, Guard, GuardMut, Lock}; +pub use guard::{CreatableLock, Guard, Lock, ReadLock, WriteLock}; pub use locked_by::LockedBy; pub use mutex::Mutex; pub use revocable_mutex::{RevocableMutex, RevocableMutexGuard}; diff --git a/rust/kernel/sync/mutex.rs b/rust/kernel/sync/mutex.rs index d6e5f11d2f7401..eacdbc3c19ac5f 100644 --- a/rust/kernel/sync/mutex.rs +++ b/rust/kernel/sync/mutex.rs @@ -4,7 +4,7 @@ //! //! This module allows Rust code to use the kernel's [`struct mutex`]. -use super::{CreatableLock, GuardMut, Lock}; +use super::{CreatableLock, Guard, Lock}; use crate::{bindings, str::CStr, Opaque}; use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin}; @@ -65,10 +65,10 @@ impl Mutex { impl Mutex { /// Locks the mutex and gives the caller access to the data protected by it. Only one thread at /// a time is allowed to access the protected data. - pub fn lock(&self) -> GuardMut<'_, Self> { + pub fn lock(&self) -> Guard<'_, Self> { let ctx = self.lock_noguard(); // SAFETY: The mutex was just acquired. - unsafe { GuardMut::new(self, ctx) } + unsafe { Guard::new(self, ctx) } } } diff --git a/rust/kernel/sync/revocable_mutex.rs b/rust/kernel/sync/revocable_mutex.rs index 0c3170213d057e..208104625ab1e1 100644 --- a/rust/kernel/sync/revocable_mutex.rs +++ b/rust/kernel/sync/revocable_mutex.rs @@ -5,7 +5,7 @@ use crate::{ bindings, str::CStr, - sync::{GuardMut, Mutex, NeedsLockClass}, + sync::{Guard, Mutex, NeedsLockClass}, }; use core::{ mem::ManuallyDrop, @@ -153,11 +153,11 @@ impl Drop for RevocableMutex { /// A guard that allows access to a revocable object and keeps it alive. pub struct RevocableMutexGuard<'a, T: ?Sized> { - guard: GuardMut<'a, Mutex>>, + guard: Guard<'a, Mutex>>, } impl<'a, T: ?Sized> RevocableMutexGuard<'a, T> { - fn new(guard: GuardMut<'a, Mutex>>) -> Self { + fn new(guard: Guard<'a, Mutex>>) -> Self { Self { guard } } diff --git a/rust/kernel/sync/seqlock.rs b/rust/kernel/sync/seqlock.rs index a45304cf0bb701..dcd4220ec44f9c 100644 --- a/rust/kernel/sync/seqlock.rs +++ b/rust/kernel/sync/seqlock.rs @@ -7,7 +7,7 @@ //! //! See . -use super::{CreatableLock, Guard, Lock, NeedsLockClass}; +use super::{CreatableLock, Guard, Lock, NeedsLockClass, ReadLock}; use crate::{bindings, str::CStr, Opaque}; use core::{cell::UnsafeCell, marker::PhantomPinned, ops::Deref, pin::Pin}; @@ -122,7 +122,7 @@ impl SeqLock { /// The guard is not mutable though because readers are still allowed to concurrently access /// the data. The protected data structure needs to provide interior mutability itself (e.g., /// via atomic types) for the individual fields that can be mutated. - pub fn write(&self) -> Guard<'_, Self> { + pub fn write(&self) -> Guard<'_, Self, ReadLock> { let ctx = self.lock_noguard(); // SAFETY: The seqlock was just acquired. unsafe { Guard::new(self, ctx) } @@ -146,7 +146,7 @@ impl NeedsLockClass for SeqLock { } // SAFETY: The underlying lock ensures mutual exclusion. -unsafe impl Lock for SeqLock { +unsafe impl Lock for SeqLock { type Inner = L::Inner; type GuardContext = L::GuardContext; diff --git a/rust/kernel/sync/spinlock.rs b/rust/kernel/sync/spinlock.rs index f4bcf57043ca21..8a1f87ad5c094d 100644 --- a/rust/kernel/sync/spinlock.rs +++ b/rust/kernel/sync/spinlock.rs @@ -6,7 +6,7 @@ //! //! See . -use super::{CreatableLock, GuardMut, Lock}; +use super::{CreatableLock, Guard, Lock}; use crate::{bindings, c_types, str::CStr, Opaque}; use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin}; @@ -108,20 +108,20 @@ impl SpinLock { impl SpinLock { /// Locks the spinlock and gives the caller access to the data protected by it. Only one thread /// at a time is allowed to access the protected data. - pub fn lock(&self) -> GuardMut<'_, Self> { + pub fn lock(&self) -> Guard<'_, Self> { let ctx = self.lock_noguard(); // SAFETY: The spinlock was just acquired. - unsafe { GuardMut::new(self, ctx) } + unsafe { Guard::new(self, ctx) } } /// Locks the spinlock and gives the caller access to the data protected by it. Additionally it /// disables interrupts (if they are enabled). /// /// When the lock in unlocked, the interrupt state (enabled/disabled) is restored. - pub fn lock_irqdisable(&self) -> GuardMut<'_, Self> { + pub fn lock_irqdisable(&self) -> Guard<'_, Self> { let ctx = self.internal_lock_irqsave(); // SAFETY: The spinlock was just acquired. - unsafe { GuardMut::new(self, Some(ctx)) } + unsafe { Guard::new(self, Some(ctx)) } } fn internal_lock_irqsave(&self) -> c_types::c_ulong {