Skip to content

Commit 9f9b29b

Browse files
authored
Merge pull request #454 from wedsonaf/guard-state
rust: allow state to be saved in lock guards.
2 parents 718f222 + 823ad67 commit 9f9b29b

File tree

4 files changed

+22
-14
lines changed

4 files changed

+22
-14
lines changed

rust/kernel/sync/condvar.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@ impl CondVar {
8181
}
8282

8383
// SAFETY: The guard is evidence that the caller owns the lock.
84-
unsafe { lock.unlock() };
84+
unsafe { lock.unlock(&mut guard.context) };
8585

8686
// SAFETY: No arguments, switches to another thread.
8787
unsafe { bindings::schedule() };
8888

89-
lock.lock_noguard();
89+
guard.context = lock.lock_noguard();
9090

9191
// SAFETY: Both `wait` and `wait_list` point to valid memory.
9292
unsafe { bindings::finish_wait(self.wait_list.get(), wait.as_mut_ptr()) };

rust/kernel/sync/guard.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#[must_use = "the lock unlocks immediately when the guard is unused"]
1313
pub struct Guard<'a, L: Lock + ?Sized> {
1414
pub(crate) lock: &'a L,
15+
pub(crate) context: L::GuardContext,
1516
}
1617

1718
// SAFETY: `Guard` is sync when the data protected by the lock is also sync. This is more
@@ -44,7 +45,7 @@ impl<L: Lock + ?Sized> core::ops::DerefMut for Guard<'_, L> {
4445
impl<L: Lock + ?Sized> Drop for Guard<'_, L> {
4546
fn drop(&mut self) {
4647
// SAFETY: The caller owns the lock, so it is safe to unlock it.
47-
unsafe { self.lock.unlock() };
48+
unsafe { self.lock.unlock(&mut self.context) };
4849
}
4950
}
5051

@@ -54,8 +55,8 @@ impl<'a, L: Lock + ?Sized> Guard<'a, L> {
5455
/// # Safety
5556
///
5657
/// The caller must ensure that it owns the lock.
57-
pub(crate) unsafe fn new(lock: &'a L) -> Self {
58-
Self { lock }
58+
pub(crate) unsafe fn new(lock: &'a L, context: L::GuardContext) -> Self {
59+
Self { lock, context }
5960
}
6061
}
6162

@@ -67,15 +68,18 @@ pub trait Lock {
6768
/// The type of the data protected by the lock.
6869
type Inner: ?Sized;
6970

71+
/// The type of context, if any, that needs to be stored in the guard.
72+
type GuardContext;
73+
7074
/// Acquires the lock, making the caller its owner.
71-
fn lock_noguard(&self);
75+
fn lock_noguard(&self) -> Self::GuardContext;
7276

7377
/// Releases the lock, giving up ownership of the lock.
7478
///
7579
/// # Safety
7680
///
7781
/// It must only be called by the current owner of the lock.
78-
unsafe fn unlock(&self);
82+
unsafe fn unlock(&self, context: &mut Self::GuardContext);
7983

8084
/// Returns the data protected by the lock.
8185
fn locked_data(&self) -> &core::cell::UnsafeCell<Self::Inner>;

rust/kernel/sync/mutex.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<T: ?Sized> Mutex<T> {
6767
pub fn lock(&self) -> Guard<'_, Self> {
6868
self.lock_noguard();
6969
// SAFETY: The mutex was just acquired.
70-
unsafe { Guard::new(self) }
70+
unsafe { Guard::new(self, ()) }
7171
}
7272
}
7373

@@ -83,15 +83,16 @@ extern "C" {
8383

8484
impl<T: ?Sized> Lock for Mutex<T> {
8585
type Inner = T;
86+
type GuardContext = ();
8687

8788
fn lock_noguard(&self) {
8889
// SAFETY: `mutex` points to valid memory.
89-
unsafe {
90-
rust_helper_mutex_lock(self.mutex.get());
91-
}
90+
unsafe { rust_helper_mutex_lock(self.mutex.get()) };
9291
}
9392

94-
unsafe fn unlock(&self) {
93+
unsafe fn unlock(&self, _: &mut ()) {
94+
// SAFETY: The safety requirements of the function ensure that the mutex is owned by the
95+
// caller.
9596
unsafe { bindings::mutex_unlock(self.mutex.get()) };
9697
}
9798

rust/kernel/sync/spinlock.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl<T: ?Sized> SpinLock<T> {
8181
pub fn lock(&self) -> Guard<'_, Self> {
8282
self.lock_noguard();
8383
// SAFETY: The spinlock was just acquired.
84-
unsafe { Guard::new(self) }
84+
unsafe { Guard::new(self, ()) }
8585
}
8686
}
8787

@@ -93,13 +93,16 @@ impl<T: ?Sized> NeedsLockClass for SpinLock<T> {
9393

9494
impl<T: ?Sized> Lock for SpinLock<T> {
9595
type Inner = T;
96+
type GuardContext = ();
9697

9798
fn lock_noguard(&self) {
9899
// SAFETY: `spin_lock` points to valid memory.
99100
unsafe { rust_helper_spin_lock(self.spin_lock.get()) };
100101
}
101102

102-
unsafe fn unlock(&self) {
103+
unsafe fn unlock(&self, _: &mut ()) {
104+
// SAFETY: The safety requirements of the function ensure that the spinlock is owned by the
105+
// caller.
103106
unsafe { rust_helper_spin_unlock(self.spin_lock.get()) };
104107
}
105108

0 commit comments

Comments
 (0)