From 11e4984df20cb7281d31f719531917ee60077afa Mon Sep 17 00:00:00 2001 From: Zhang Junyang Date: Tue, 23 Apr 2024 09:15:29 +0800 Subject: [PATCH] Allow dynamically borrowed `RwLock` guards --- framework/aster-frame/src/sync/mod.rs | 5 +- framework/aster-frame/src/sync/rwlock.rs | 177 +++++++++++++++--- .../src/process/credentials/credentials_.rs | 4 +- .../src/process/credentials/static_cap.rs | 4 +- 4 files changed, 158 insertions(+), 32 deletions(-) diff --git a/framework/aster-frame/src/sync/mod.rs b/framework/aster-frame/src/sync/mod.rs index 4b65d717a..516d4c9a4 100644 --- a/framework/aster-frame/src/sync/mod.rs +++ b/framework/aster-frame/src/sync/mod.rs @@ -14,7 +14,10 @@ mod wait; pub use self::{ atomic_bits::AtomicBits, mutex::{Mutex, MutexGuard}, - rwlock::{RwLock, RwLockReadGuard, RwLockUpgradeableGuard, RwLockWriteGuard}, + rwlock::{ + ArcRwLockReadGuard, ArcRwLockUpgradeableGuard, ArcRwLockWriteGuard, RwLock, + RwLockReadGuard, RwLockUpgradeableGuard, RwLockWriteGuard, + }, rwmutex::{RwMutex, RwMutexReadGuard, RwMutexUpgradeableGuard, RwMutexWriteGuard}, spin::{ArcSpinLockGuard, SpinLock, SpinLockGuard}, wait::WaitQueue, diff --git a/framework/aster-frame/src/sync/rwlock.rs b/framework/aster-frame/src/sync/rwlock.rs index a5626b7de..679df2c8d 100644 --- a/framework/aster-frame/src/sync/rwlock.rs +++ b/framework/aster-frame/src/sync/rwlock.rs @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 +use alloc::sync::Arc; use core::{ cell::UnsafeCell, fmt, @@ -265,6 +266,20 @@ impl RwLock { } } + /// Acquire a read lock through an [`Arc`]. + /// + /// The method is similar to [`Self::read`], but it doesn't have the requirement + /// for compile-time checked lifetimes of the read guard. + pub fn read_arc(self: &Arc) -> ArcRwLockReadGuard { + loop { + if let Some(readguard) = self.try_read_arc() { + return readguard; + } else { + core::hint::spin_loop(); + } + } + } + /// Acquire a write lock and spin-wait until it can be acquired. /// /// The calling thread will spin-wait until there are no other writers, @@ -287,6 +302,20 @@ impl RwLock { } } + /// Acquire a write lock through an [`Arc`]. + /// + /// The method is similar to [`Self::write`], but it doesn't have the requirement + /// for compile-time checked lifetimes of the lock guard. + pub fn write_arc(self: &Arc) -> ArcRwLockWriteGuard { + loop { + if let Some(writeguard) = self.try_write_arc() { + return writeguard; + } else { + core::hint::spin_loop(); + } + } + } + /// Acquire an upreader and spin-wait until it can be acquired. /// /// The calling thread will spin-wait until there are no other writers, @@ -313,6 +342,20 @@ impl RwLock { } } + /// Acquire an upgradeable read lock through an [`Arc`]. + /// + /// The method is similar to [`Self::upread`], but it doesn't have the requirement + /// for compile-time checked lifetimes of the lock guard. + pub fn upread_arc(self: &Arc) -> ArcRwLockUpgradeableGuard { + loop { + if let Some(guard) = self.try_upread_arc() { + return guard; + } else { + core::hint::spin_loop(); + } + } + } + /// Attempt to acquire a read lock. /// /// This function will never spin-wait and will return immediately. @@ -337,6 +380,24 @@ impl RwLock { } } + /// Attempt to acquire an read lock through an [`Arc`]. + /// + /// The method is similar to [`Self::try_read`], but it doesn't have the requirement + /// for compile-time checked lifetimes of the lock guard. + pub fn try_read_arc(self: &Arc) -> Option> { + let guard = disable_preempt(); + let lock = self.lock.fetch_add(READER, Acquire); + if lock & (WRITER | MAX_READER | BEING_UPGRADED) == 0 { + Some(ArcRwLockReadGuard { + inner: self.clone(), + inner_guard: InnerGuard::PreemptGuard(guard), + }) + } else { + self.lock.fetch_sub(READER, Release); + None + } + } + /// Attempt to acquire a write lock. /// /// This function will never spin-wait and will return immediately. @@ -363,6 +424,26 @@ impl RwLock { } } + /// Attempt to acquire a write lock through an [`Arc`]. + /// + /// The method is similar to [`Self::try_write`], but it doesn't have the requirement + /// for compile-time checked lifetimes of the lock guard. + fn try_write_arc(self: &Arc) -> Option> { + let guard = disable_preempt(); + if self + .lock + .compare_exchange(0, WRITER, Acquire, Relaxed) + .is_ok() + { + Some(ArcRwLockWriteGuard { + inner: self.clone(), + inner_guard: InnerGuard::PreemptGuard(guard), + }) + } else { + None + } + } + /// Attempt to acquire an upread lock. /// /// This function will never spin-wait and will return immediately. @@ -386,6 +467,24 @@ impl RwLock { } None } + + /// Attempt to acquire an upgradeable read lock through an [`Arc`]. + /// + /// The method is similar to [`Self::try_upread`], but it doesn't have the requirement + /// for compile-time checked lifetimes of the lock guard. + pub fn try_upread_arc(self: &Arc) -> Option> { + let guard = disable_preempt(); + let lock = self.lock.fetch_or(UPGRADEABLE_READER, Acquire) & (WRITER | UPGRADEABLE_READER); + if lock == 0 { + return Some(ArcRwLockUpgradeableGuard { + inner: self.clone(), + inner_guard: InnerGuard::PreemptGuard(guard), + }); + } else if lock == WRITER { + self.lock.fetch_sub(UPGRADEABLE_READER, Release); + } + None + } } impl fmt::Debug for RwLock { @@ -399,14 +498,23 @@ impl fmt::Debug for RwLock { unsafe impl Send for RwLock {} unsafe impl Sync for RwLock {} -impl<'a, T: ?Sized> !Send for RwLockWriteGuard<'a, T> {} -unsafe impl Sync for RwLockWriteGuard<'_, T> {} +impl> + Clone> !Send for RwLockWriteGuard_ {} +unsafe impl> + Clone + Sync> Sync + for RwLockWriteGuard_ +{ +} -impl<'a, T: ?Sized> !Send for RwLockReadGuard<'a, T> {} -unsafe impl Sync for RwLockReadGuard<'_, T> {} +impl> + Clone> !Send for RwLockReadGuard_ {} +unsafe impl> + Clone + Sync> Sync + for RwLockReadGuard_ +{ +} -impl<'a, T: ?Sized> !Send for RwLockUpgradeableGuard<'a, T> {} -unsafe impl Sync for RwLockUpgradeableGuard<'_, T> {} +impl> + Clone> !Send for RwLockUpgradeableGuard_ {} +unsafe impl> + Clone + Sync> Sync + for RwLockUpgradeableGuard_ +{ +} enum InnerGuard { IrqGuard(DisabledLocalIrqGuard), @@ -414,12 +522,15 @@ enum InnerGuard { } /// A guard that provides immutable data access. -pub struct RwLockReadGuard<'a, T: ?Sized> { +pub struct RwLockReadGuard_> + Clone> { inner_guard: InnerGuard, - inner: &'a RwLock, + inner: R, } -impl<'a, T: ?Sized> Deref for RwLockReadGuard<'a, T> { +pub type RwLockReadGuard<'a, T> = RwLockReadGuard_>; +pub type ArcRwLockReadGuard = RwLockReadGuard_>>; + +impl> + Clone> Deref for RwLockReadGuard_ { type Target = T; fn deref(&self) -> &T { @@ -427,25 +538,30 @@ impl<'a, T: ?Sized> Deref for RwLockReadGuard<'a, T> { } } -impl<'a, T: ?Sized> Drop for RwLockReadGuard<'a, T> { +impl> + Clone> Drop for RwLockReadGuard_ { fn drop(&mut self) { self.inner.lock.fetch_sub(READER, Release); } } -impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> { +impl> + Clone> fmt::Debug + for RwLockReadGuard_ +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } /// A guard that provides mutable data access. -pub struct RwLockWriteGuard<'a, T: ?Sized> { +pub struct RwLockWriteGuard_> + Clone> { inner_guard: InnerGuard, - inner: &'a RwLock, + inner: R, } -impl<'a, T: ?Sized> Deref for RwLockWriteGuard<'a, T> { +pub type RwLockWriteGuard<'a, T> = RwLockWriteGuard_>; +pub type ArcRwLockWriteGuard = RwLockWriteGuard_>>; + +impl> + Clone> Deref for RwLockWriteGuard_ { type Target = T; fn deref(&self) -> &T { @@ -453,19 +569,21 @@ impl<'a, T: ?Sized> Deref for RwLockWriteGuard<'a, T> { } } -impl<'a, T: ?Sized> DerefMut for RwLockWriteGuard<'a, T> { +impl> + Clone> DerefMut for RwLockWriteGuard_ { fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *self.inner.val.get() } } } -impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> { +impl> + Clone> Drop for RwLockWriteGuard_ { fn drop(&mut self) { self.inner.lock.fetch_and(!WRITER, Release); } } -impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> { +impl> + Clone> fmt::Debug + for RwLockWriteGuard_ +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } @@ -473,18 +591,21 @@ impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> { /// A guard that provides immutable data access but can be atomically /// upgraded to `RwLockWriteGuard`. -pub struct RwLockUpgradeableGuard<'a, T: ?Sized> { +pub struct RwLockUpgradeableGuard_> + Clone> { inner_guard: InnerGuard, - inner: &'a RwLock, + inner: R, } -impl<'a, T: ?Sized> RwLockUpgradeableGuard<'a, T> { +pub type RwLockUpgradeableGuard<'a, T> = RwLockUpgradeableGuard_>; +pub type ArcRwLockUpgradeableGuard = RwLockUpgradeableGuard_>>; + +impl> + Clone> RwLockUpgradeableGuard_ { /// Upgrade this upread guard to a write guard atomically. /// /// After calling this method, subsequent readers will be blocked /// while previous readers remain unaffected. The calling thread /// will spin-wait until previous readers finish. - pub fn upgrade(mut self) -> RwLockWriteGuard<'a, T> { + pub fn upgrade(mut self) -> RwLockWriteGuard_ { self.inner.lock.fetch_or(BEING_UPGRADED, Acquire); loop { self = match self.try_upgrade() { @@ -496,8 +617,7 @@ impl<'a, T: ?Sized> RwLockUpgradeableGuard<'a, T> { /// Attempts to upgrade this upread guard to a write guard atomically. /// /// This function will never spin-wait and will return immediately. - pub fn try_upgrade(mut self) -> Result, Self> { - let inner = self.inner; + pub fn try_upgrade(mut self) -> Result, Self> { let res = self.inner.lock.compare_exchange( UPGRADEABLE_READER | BEING_UPGRADED, WRITER | UPGRADEABLE_READER, @@ -511,15 +631,16 @@ impl<'a, T: ?Sized> RwLockUpgradeableGuard<'a, T> { InnerGuard::PreemptGuard(preempt_guard.transfer_to()) } }; + let inner = self.inner.clone(); drop(self); - Ok(RwLockWriteGuard { inner, inner_guard }) + Ok(RwLockWriteGuard_ { inner, inner_guard }) } else { Err(self) } } } -impl<'a, T: ?Sized> Deref for RwLockUpgradeableGuard<'a, T> { +impl> + Clone> Deref for RwLockUpgradeableGuard_ { type Target = T; fn deref(&self) -> &T { @@ -527,13 +648,15 @@ impl<'a, T: ?Sized> Deref for RwLockUpgradeableGuard<'a, T> { } } -impl<'a, T: ?Sized> Drop for RwLockUpgradeableGuard<'a, T> { +impl> + Clone> Drop for RwLockUpgradeableGuard_ { fn drop(&mut self) { self.inner.lock.fetch_sub(UPGRADEABLE_READER, Release); } } -impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for RwLockUpgradeableGuard<'a, T> { +impl> + Clone> fmt::Debug + for RwLockUpgradeableGuard_ +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } diff --git a/kernel/aster-nix/src/process/credentials/credentials_.rs b/kernel/aster-nix/src/process/credentials/credentials_.rs index 941eb1307..0fbfdde02 100644 --- a/kernel/aster-nix/src/process/credentials/credentials_.rs +++ b/kernel/aster-nix/src/process/credentials/credentials_.rs @@ -364,11 +364,11 @@ impl Credentials_ { } // ******* Supplementary groups methods ******* - pub(super) fn groups(&self) -> RwLockReadGuard<'_, BTreeSet> { + pub(super) fn groups(&self) -> RwLockReadGuard> { self.supplementary_gids.read() } - pub(super) fn groups_mut(&self) -> RwLockWriteGuard<'_, BTreeSet> { + pub(super) fn groups_mut(&self) -> RwLockWriteGuard> { self.supplementary_gids.write() } } diff --git a/kernel/aster-nix/src/process/credentials/static_cap.rs b/kernel/aster-nix/src/process/credentials/static_cap.rs index 0514ff210..c7117f9d5 100644 --- a/kernel/aster-nix/src/process/credentials/static_cap.rs +++ b/kernel/aster-nix/src/process/credentials/static_cap.rs @@ -236,7 +236,7 @@ impl Credentials { /// /// This method requies the `Read` right. #[require(R > Read)] - pub fn groups(&self) -> RwLockReadGuard<'_, BTreeSet> { + pub fn groups(&self) -> RwLockReadGuard> { self.0.groups() } @@ -244,7 +244,7 @@ impl Credentials { /// /// This method requires the `Write` right. #[require(R > Write)] - pub fn groups_mut(&self) -> RwLockWriteGuard<'_, BTreeSet> { + pub fn groups_mut(&self) -> RwLockWriteGuard> { self.0.groups_mut() } }