mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 17:03:23 +00:00
Allow dynamically borrowed mutex guard
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
11e4984df2
commit
d15b4d9115
@ -13,7 +13,7 @@ mod wait;
|
|||||||
// pub use self::rcu::{pass_quiescent_state, OwnerPtr, Rcu, RcuReadGuard, RcuReclaimer};
|
// pub use self::rcu::{pass_quiescent_state, OwnerPtr, Rcu, RcuReadGuard, RcuReclaimer};
|
||||||
pub use self::{
|
pub use self::{
|
||||||
atomic_bits::AtomicBits,
|
atomic_bits::AtomicBits,
|
||||||
mutex::{Mutex, MutexGuard},
|
mutex::{ArcMutexGuard, Mutex, MutexGuard},
|
||||||
rwlock::{
|
rwlock::{
|
||||||
ArcRwLockReadGuard, ArcRwLockUpgradeableGuard, ArcRwLockWriteGuard, RwLock,
|
ArcRwLockReadGuard, ArcRwLockUpgradeableGuard, ArcRwLockWriteGuard, RwLock,
|
||||||
RwLockReadGuard, RwLockUpgradeableGuard, RwLockWriteGuard,
|
RwLockReadGuard, RwLockUpgradeableGuard, RwLockWriteGuard,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use alloc::sync::Arc;
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
fmt,
|
fmt,
|
||||||
@ -35,11 +36,29 @@ impl<T: ?Sized> Mutex<T> {
|
|||||||
self.queue.wait_until(|| self.try_lock())
|
self.queue.wait_until(|| self.try_lock())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Acquire the mutex through an [`Arc`].
|
||||||
|
///
|
||||||
|
/// The method is similar to [`Self::lock`], but it doesn't have the requirement
|
||||||
|
/// for compile-time checked lifetimes of the mutex guard.
|
||||||
|
pub fn lock_arc(self: &Arc<Self>) -> ArcMutexGuard<T> {
|
||||||
|
self.queue.wait_until(|| self.try_lock_arc())
|
||||||
|
}
|
||||||
|
|
||||||
/// Try Acquire the mutex immedidately.
|
/// Try Acquire the mutex immedidately.
|
||||||
pub fn try_lock(&self) -> Option<MutexGuard<T>> {
|
pub fn try_lock(&self) -> Option<MutexGuard<T>> {
|
||||||
// Cannot be reduced to `then_some`, or the possible dropping of the temporary
|
// Cannot be reduced to `then_some`, or the possible dropping of the temporary
|
||||||
// guard will cause an unexpected unlock.
|
// guard will cause an unexpected unlock.
|
||||||
self.acquire_lock().then(|| MutexGuard::new(self))
|
self.acquire_lock().then_some(MutexGuard { mutex: self })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try acquire the mutex through an [`Arc`].
|
||||||
|
///
|
||||||
|
/// The method is similar to [`Self::try_lock`], but it doesn't have the requirement
|
||||||
|
/// for compile-time checked lifetimes of the mutex guard.
|
||||||
|
pub fn try_lock_arc(self: &Arc<Self>) -> Option<ArcMutexGuard<T>> {
|
||||||
|
self.acquire_lock().then(|| ArcMutexGuard {
|
||||||
|
mutex: self.clone(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Release the mutex and wake up one thread which is blocked on this mutex.
|
/// Release the mutex and wake up one thread which is blocked on this mutex.
|
||||||
@ -69,17 +88,14 @@ unsafe impl<T: ?Sized + Send> Send for Mutex<T> {}
|
|||||||
unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
|
unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
|
||||||
|
|
||||||
#[clippy::has_significant_drop]
|
#[clippy::has_significant_drop]
|
||||||
pub struct MutexGuard<'a, T: ?Sized> {
|
pub struct MutexGuard_<T: ?Sized, R: Deref<Target = Mutex<T>>> {
|
||||||
mutex: &'a Mutex<T>,
|
mutex: R,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: ?Sized> MutexGuard<'a, T> {
|
pub type MutexGuard<'a, T> = MutexGuard_<T, &'a Mutex<T>>;
|
||||||
fn new(mutex: &'a Mutex<T>) -> MutexGuard<'a, T> {
|
pub type ArcMutexGuard<T> = MutexGuard_<T, Arc<Mutex<T>>>;
|
||||||
MutexGuard { mutex }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
|
impl<T: ?Sized, R: Deref<Target = Mutex<T>>> Deref for MutexGuard_<T, R> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@ -87,24 +103,24 @@ impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
|
impl<T: ?Sized, R: Deref<Target = Mutex<T>>> DerefMut for MutexGuard_<T, R> {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
unsafe { &mut *self.mutex.val.get() }
|
unsafe { &mut *self.mutex.val.get() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
|
impl<T: ?Sized, R: Deref<Target = Mutex<T>>> Drop for MutexGuard_<T, R> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.mutex.unlock();
|
self.mutex.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
|
impl<T: ?Sized + fmt::Debug, R: Deref<Target = Mutex<T>>> fmt::Debug for MutexGuard_<T, R> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Debug::fmt(&**self, f)
|
fmt::Debug::fmt(&**self, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: ?Sized> !Send for MutexGuard<'a, T> {}
|
impl<T: ?Sized, R: Deref<Target = Mutex<T>>> !Send for MutexGuard_<T, R> {}
|
||||||
|
|
||||||
unsafe impl<T: ?Sized + Sync> Sync for MutexGuard<'_, T> {}
|
unsafe impl<T: ?Sized + Sync, R: Deref<Target = Mutex<T>> + Sync> Sync for MutexGuard_<T, R> {}
|
||||||
|
@ -202,7 +202,7 @@ impl ExfatChain {
|
|||||||
fn alloc_cluster_from_empty(
|
fn alloc_cluster_from_empty(
|
||||||
&mut self,
|
&mut self,
|
||||||
num_to_be_allocated: u32,
|
num_to_be_allocated: u32,
|
||||||
bitmap: &mut MutexGuard<'_, ExfatBitmap>,
|
bitmap: &mut MutexGuard<ExfatBitmap>,
|
||||||
sync_bitmap: bool,
|
sync_bitmap: bool,
|
||||||
) -> Result<ClusterID> {
|
) -> Result<ClusterID> {
|
||||||
// Search for a continuous chunk big enough
|
// Search for a continuous chunk big enough
|
||||||
@ -228,7 +228,7 @@ impl ExfatChain {
|
|||||||
&mut self,
|
&mut self,
|
||||||
num_to_be_allocated: u32,
|
num_to_be_allocated: u32,
|
||||||
sync: bool,
|
sync: bool,
|
||||||
bitmap: &mut MutexGuard<'_, ExfatBitmap>,
|
bitmap: &mut MutexGuard<ExfatBitmap>,
|
||||||
) -> Result<ClusterID> {
|
) -> Result<ClusterID> {
|
||||||
let fs = self.fs();
|
let fs = self.fs();
|
||||||
let mut alloc_start_cluster = 0;
|
let mut alloc_start_cluster = 0;
|
||||||
@ -255,7 +255,7 @@ impl ExfatChain {
|
|||||||
start_physical_cluster: ClusterID,
|
start_physical_cluster: ClusterID,
|
||||||
drop_num: u32,
|
drop_num: u32,
|
||||||
sync_bitmap: bool,
|
sync_bitmap: bool,
|
||||||
bitmap: &mut MutexGuard<'_, ExfatBitmap>,
|
bitmap: &mut MutexGuard<ExfatBitmap>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let fs = self.fs();
|
let fs = self.fs();
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ impl ExfatFS {
|
|||||||
self.super_block.cluster_size as usize * self.super_block.num_clusters as usize
|
self.super_block.cluster_size as usize * self.super_block.num_clusters as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn lock(&self) -> MutexGuard<'_, ()> {
|
pub(super) fn lock(&self) -> MutexGuard<()> {
|
||||||
self.mutex.lock()
|
self.mutex.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user