Skip to content

Commit d37432d

Browse files
authored
Merge pull request #628 from wedsonaf/guard-marker
rust: simplify lock guards by using marker types
2 parents 9646c0e + b337bfa commit d37432d

File tree

10 files changed

+62
-93
lines changed

10 files changed

+62
-93
lines changed

drivers/android/node.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use kernel::{
55
io_buffer::IoBufferWriter,
66
linked_list::{GetLinks, Links, List},
77
prelude::*,
8-
sync::{GuardMut, LockedBy, Mutex, Ref, SpinLock},
8+
sync::{Guard, LockedBy, Mutex, Ref, SpinLock},
99
user_ptr::UserSlicePtrWriter,
1010
};
1111

@@ -244,15 +244,15 @@ impl Node {
244244

245245
pub(crate) fn next_death(
246246
&self,
247-
guard: &mut GuardMut<'_, Mutex<ProcessInner>>,
247+
guard: &mut Guard<'_, Mutex<ProcessInner>>,
248248
) -> Option<Ref<NodeDeath>> {
249249
self.inner.access_mut(guard).death_list.pop_front()
250250
}
251251

252252
pub(crate) fn add_death(
253253
&self,
254254
death: Ref<NodeDeath>,
255-
guard: &mut GuardMut<'_, Mutex<ProcessInner>>,
255+
guard: &mut Guard<'_, Mutex<ProcessInner>>,
256256
) {
257257
self.inner.access_mut(guard).death_list.push_back(death);
258258
}
@@ -306,7 +306,7 @@ impl Node {
306306
pub(crate) fn populate_counts(
307307
&self,
308308
out: &mut BinderNodeInfoForRef,
309-
guard: &GuardMut<'_, Mutex<ProcessInner>>,
309+
guard: &Guard<'_, Mutex<ProcessInner>>,
310310
) {
311311
let inner = self.inner.access(guard);
312312
out.strong_count = inner.strong.count as _;
@@ -316,7 +316,7 @@ impl Node {
316316
pub(crate) fn populate_debug_info(
317317
&self,
318318
out: &mut BinderNodeDebugInfo,
319-
guard: &GuardMut<'_, Mutex<ProcessInner>>,
319+
guard: &Guard<'_, Mutex<ProcessInner>>,
320320
) {
321321
out.ptr = self.ptr as _;
322322
out.cookie = self.cookie as _;
@@ -329,7 +329,7 @@ impl Node {
329329
}
330330
}
331331

332-
pub(crate) fn force_has_count(&self, guard: &mut GuardMut<'_, Mutex<ProcessInner>>) {
332+
pub(crate) fn force_has_count(&self, guard: &mut Guard<'_, Mutex<ProcessInner>>) {
333333
let inner = self.inner.access_mut(guard);
334334
inner.strong.has_count = true;
335335
inner.weak.has_count = true;

drivers/android/process.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use kernel::{
1111
pages::Pages,
1212
prelude::*,
1313
rbtree::RBTree,
14-
sync::{GuardMut, Mutex, Ref, RefBorrow, UniqueRef},
14+
sync::{Guard, Mutex, Ref, RefBorrow, UniqueRef},
1515
task::Task,
1616
user_ptr::{UserSlicePtr, UserSlicePtrReader},
1717
};
@@ -949,7 +949,7 @@ impl<'a> Registration<'a> {
949949
fn new(
950950
process: &'a Process,
951951
thread: &'a Ref<Thread>,
952-
guard: &mut GuardMut<'_, Mutex<ProcessInner>>,
952+
guard: &mut Guard<'_, Mutex<ProcessInner>>,
953953
) -> Self {
954954
guard.ready_threads.push_back(thread.clone());
955955
Self { process, thread }

rust/kernel/sync/condvar.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//! This module allows Rust code to use the kernel's [`struct wait_queue_head`] as a condition
66
//! variable.
77
8-
use super::{GuardMut, Lock, NeedsLockClass};
8+
use super::{Guard, Lock, NeedsLockClass};
99
use crate::{bindings, str::CStr, task::Task, Opaque};
1010
use core::{marker::PhantomPinned, pin::Pin};
1111

@@ -61,8 +61,8 @@ impl CondVar {
6161
///
6262
/// Returns whether there is a signal pending.
6363
#[must_use = "wait returns if a signal is pending, so the caller must check the return value"]
64-
pub fn wait<L: Lock>(&self, guard: &mut GuardMut<'_, L>) -> bool {
65-
let lock = guard.guard.lock;
64+
pub fn wait<L: Lock<M>, M>(&self, guard: &mut Guard<'_, L, M>) -> bool {
65+
let lock = guard.lock;
6666
let wait = Opaque::<bindings::wait_queue_entry>::uninit();
6767

6868
// SAFETY: `wait` points to valid memory.
@@ -78,12 +78,12 @@ impl CondVar {
7878
};
7979

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

8383
// SAFETY: No arguments, switches to another thread.
8484
unsafe { bindings::schedule() };
8585

86-
lock.relock(&mut guard.guard.context);
86+
lock.relock(&mut guard.context);
8787

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

rust/kernel/sync/guard.rs

Lines changed: 29 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,55 +14,7 @@ use core::pin::Pin;
1414
/// when a guard goes out of scope. It also provides a safe and convenient way to access the data
1515
/// protected by the lock.
1616
#[must_use = "the lock unlocks immediately when the guard is unused"]
17-
pub struct GuardMut<'a, L: Lock + ?Sized> {
18-
pub(crate) guard: Guard<'a, L>,
19-
}
20-
21-
// SAFETY: `GuardMut` is sync when the data protected by the lock is also sync. This is more
22-
// conservative than the default compiler implementation; more details can be found on
23-
// https://github.com/rust-lang/rust/issues/41622 -- it refers to `MutexGuard` from the standard
24-
// library.
25-
unsafe impl<L> Sync for GuardMut<'_, L>
26-
where
27-
L: Lock + ?Sized,
28-
L::Inner: Sync,
29-
{
30-
}
31-
32-
impl<L: Lock + ?Sized> core::ops::Deref for GuardMut<'_, L> {
33-
type Target = L::Inner;
34-
35-
fn deref(&self) -> &Self::Target {
36-
self.guard.deref()
37-
}
38-
}
39-
40-
impl<L: Lock + ?Sized> core::ops::DerefMut for GuardMut<'_, L> {
41-
fn deref_mut(&mut self) -> &mut L::Inner {
42-
// SAFETY: The caller owns the lock, so it is safe to deref the protected data.
43-
unsafe { &mut *self.guard.lock.locked_data().get() }
44-
}
45-
}
46-
47-
impl<'a, L: Lock + ?Sized> GuardMut<'a, L> {
48-
/// Constructs a new lock guard.
49-
///
50-
/// # Safety
51-
///
52-
/// The caller must ensure that it owns the lock.
53-
pub(crate) unsafe fn new(lock: &'a L, context: L::GuardContext) -> Self {
54-
// SAFETY: The safety requirements for this function satisfy the `Guard::new` ones.
55-
Self {
56-
guard: unsafe { Guard::new(lock, context) },
57-
}
58-
}
59-
}
60-
61-
/// Allows mutual exclusion primitives that implement the [`Lock`] trait to automatically unlock
62-
/// when a guard goes out of scope. It also provides a safe and convenient way to immutably access
63-
/// the data protected by the lock.
64-
#[must_use = "the lock unlocks immediately when the guard is unused"]
65-
pub struct Guard<'a, L: Lock + ?Sized> {
17+
pub struct Guard<'a, L: Lock<M> + ?Sized, M = WriteLock> {
6618
pub(crate) lock: &'a L,
6719
pub(crate) context: L::GuardContext,
6820
}
@@ -71,14 +23,14 @@ pub struct Guard<'a, L: Lock + ?Sized> {
7123
// conservative than the default compiler implementation; more details can be found on
7224
// https://github.com/rust-lang/rust/issues/41622 -- it refers to `MutexGuard` from the standard
7325
// library.
74-
unsafe impl<L> Sync for Guard<'_, L>
26+
unsafe impl<L, M> Sync for Guard<'_, L, M>
7527
where
76-
L: Lock + ?Sized,
28+
L: Lock<M> + ?Sized,
7729
L::Inner: Sync,
7830
{
7931
}
8032

81-
impl<L: Lock + ?Sized> core::ops::Deref for Guard<'_, L> {
33+
impl<L: Lock<M> + ?Sized, M> core::ops::Deref for Guard<'_, L, M> {
8234
type Target = L::Inner;
8335

8436
fn deref(&self) -> &Self::Target {
@@ -87,14 +39,21 @@ impl<L: Lock + ?Sized> core::ops::Deref for Guard<'_, L> {
8739
}
8840
}
8941

90-
impl<L: Lock + ?Sized> Drop for Guard<'_, L> {
42+
impl<L: Lock<WriteLock> + ?Sized> core::ops::DerefMut for Guard<'_, L, WriteLock> {
43+
fn deref_mut(&mut self) -> &mut Self::Target {
44+
// SAFETY: The caller owns the lock, so it is safe to deref the protected data.
45+
unsafe { &mut *self.lock.locked_data().get() }
46+
}
47+
}
48+
49+
impl<L: Lock<M> + ?Sized, M> Drop for Guard<'_, L, M> {
9150
fn drop(&mut self) {
9251
// SAFETY: The caller owns the lock, so it is safe to unlock it.
9352
unsafe { self.lock.unlock(&mut self.context) };
9453
}
9554
}
9655

97-
impl<'a, L: Lock + ?Sized> Guard<'a, L> {
56+
impl<'a, L: Lock<M> + ?Sized, M> Guard<'a, L, M> {
9857
/// Constructs a new immutable lock guard.
9958
///
10059
/// # Safety
@@ -105,16 +64,26 @@ impl<'a, L: Lock + ?Sized> Guard<'a, L> {
10564
}
10665
}
10766

67+
/// A marker for locks that only allow reading.
68+
pub struct ReadLock;
69+
70+
/// A marker for locks that allow reading and writing.
71+
pub struct WriteLock;
72+
10873
/// A generic mutual exclusion primitive.
10974
///
110-
/// [`Guard`] and [`GuardMut`] are written such that any mutual exclusion primitive that can
111-
/// implement this trait can also benefit from having an automatic way to unlock itself.
75+
/// [`Guard`] is written such that any mutual exclusion primitive that can implement this trait can
76+
/// also benefit from having an automatic way to unlock itself.
11277
///
11378
/// # Safety
11479
///
115-
/// Implementers of this trait must ensure that only one thread/CPU may access the protected data
116-
/// once the lock is held, that is, between calls to `lock_noguard` and `unlock`.
117-
pub unsafe trait Lock {
80+
/// - Implementers of this trait with the [`WriteLock`] marker must ensure that only one thread/CPU
81+
/// may access the protected data once the lock is held, that is, between calls to `lock_noguard`
82+
/// and `unlock`.
83+
/// - Implementers of all other markers must ensure that a mutable reference to the protected data
84+
/// is not active in any thread/CPU because at least one shared refence is active between calls
85+
/// to `lock_noguard` and `unlock`.
86+
pub unsafe trait Lock<M = WriteLock> {
11887
/// The type of the data protected by the lock.
11988
type Inner: ?Sized;
12089

@@ -147,7 +116,7 @@ pub unsafe trait Lock {
147116
}
148117

149118
/// A generic mutual exclusion primitive that can be instantiated generically.
150-
pub trait CreatableLock: Lock {
119+
pub trait CreatableLock<M = WriteLock>: Lock<M> {
151120
/// Constructs a new instance of the lock.
152121
///
153122
/// # Safety

rust/kernel/sync/locked_by.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
//! A wrapper for data protected by a lock that does not wrap it.
44
5-
use super::{GuardMut, Lock};
5+
use super::{Guard, Lock};
66
use core::{cell::UnsafeCell, ops::Deref, ptr};
77

88
/// Allows access to some data to be serialised by a lock that does not wrap it.
@@ -77,8 +77,8 @@ impl<T, L: Lock + ?Sized> LockedBy<T, L> {
7777

7878
impl<T: ?Sized, L: Lock + ?Sized> LockedBy<T, L> {
7979
/// Returns a reference to the protected data when the caller provides evidence (via a
80-
/// [`GuardMut`]) that the owner is locked.
81-
pub fn access<'a>(&'a self, guard: &'a GuardMut<'_, L>) -> &'a T {
80+
/// [`Guard`]) that the owner is locked.
81+
pub fn access<'a>(&'a self, guard: &'a Guard<'_, L>) -> &'a T {
8282
if !ptr::eq(guard.deref(), self.owner) {
8383
panic!("guard does not match owner");
8484
}
@@ -88,8 +88,8 @@ impl<T: ?Sized, L: Lock + ?Sized> LockedBy<T, L> {
8888
}
8989

9090
/// Returns a mutable reference to the protected data when the caller provides evidence (via a
91-
/// mutable [`GuardMut`]) that the owner is locked mutably.
92-
pub fn access_mut<'a>(&'a self, guard: &'a mut GuardMut<'_, L>) -> &'a mut T {
91+
/// mutable [`Guard`]) that the owner is locked mutably.
92+
pub fn access_mut<'a>(&'a self, guard: &'a mut Guard<'_, L>) -> &'a mut T {
9393
if !ptr::eq(guard.deref().deref(), self.owner) {
9494
panic!("guard does not match owner");
9595
}

rust/kernel/sync/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ mod spinlock;
3434

3535
pub use arc::{Ref, RefBorrow, UniqueRef};
3636
pub use condvar::CondVar;
37-
pub use guard::{CreatableLock, Guard, GuardMut, Lock};
37+
pub use guard::{CreatableLock, Guard, Lock, ReadLock, WriteLock};
3838
pub use locked_by::LockedBy;
3939
pub use mutex::Mutex;
4040
pub use revocable_mutex::{RevocableMutex, RevocableMutexGuard};

rust/kernel/sync/mutex.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//!
55
//! This module allows Rust code to use the kernel's [`struct mutex`].
66
7-
use super::{CreatableLock, GuardMut, Lock};
7+
use super::{CreatableLock, Guard, Lock};
88
use crate::{bindings, str::CStr, Opaque};
99
use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin};
1010

@@ -65,10 +65,10 @@ impl<T> Mutex<T> {
6565
impl<T: ?Sized> Mutex<T> {
6666
/// Locks the mutex and gives the caller access to the data protected by it. Only one thread at
6767
/// a time is allowed to access the protected data.
68-
pub fn lock(&self) -> GuardMut<'_, Self> {
68+
pub fn lock(&self) -> Guard<'_, Self> {
6969
let ctx = self.lock_noguard();
7070
// SAFETY: The mutex was just acquired.
71-
unsafe { GuardMut::new(self, ctx) }
71+
unsafe { Guard::new(self, ctx) }
7272
}
7373
}
7474

rust/kernel/sync/revocable_mutex.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use crate::{
66
bindings,
77
str::CStr,
8-
sync::{GuardMut, Mutex, NeedsLockClass},
8+
sync::{Guard, Mutex, NeedsLockClass},
99
};
1010
use core::{
1111
mem::ManuallyDrop,
@@ -153,11 +153,11 @@ impl<T: ?Sized> Drop for RevocableMutex<T> {
153153

154154
/// A guard that allows access to a revocable object and keeps it alive.
155155
pub struct RevocableMutexGuard<'a, T: ?Sized> {
156-
guard: GuardMut<'a, Mutex<RevocableMutexInner<T>>>,
156+
guard: Guard<'a, Mutex<RevocableMutexInner<T>>>,
157157
}
158158

159159
impl<'a, T: ?Sized> RevocableMutexGuard<'a, T> {
160-
fn new(guard: GuardMut<'a, Mutex<RevocableMutexInner<T>>>) -> Self {
160+
fn new(guard: Guard<'a, Mutex<RevocableMutexInner<T>>>) -> Self {
161161
Self { guard }
162162
}
163163

rust/kernel/sync/seqlock.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//!
88
//! See <https://www.kernel.org/doc/Documentation/locking/seqlock.rst>.
99
10-
use super::{CreatableLock, Guard, Lock, NeedsLockClass};
10+
use super::{CreatableLock, Guard, Lock, NeedsLockClass, ReadLock};
1111
use crate::{bindings, str::CStr, Opaque};
1212
use core::{cell::UnsafeCell, marker::PhantomPinned, ops::Deref, pin::Pin};
1313

@@ -122,7 +122,7 @@ impl<L: CreatableLock + ?Sized> SeqLock<L> {
122122
/// The guard is not mutable though because readers are still allowed to concurrently access
123123
/// the data. The protected data structure needs to provide interior mutability itself (e.g.,
124124
/// via atomic types) for the individual fields that can be mutated.
125-
pub fn write(&self) -> Guard<'_, Self> {
125+
pub fn write(&self) -> Guard<'_, Self, ReadLock> {
126126
let ctx = self.lock_noguard();
127127
// SAFETY: The seqlock was just acquired.
128128
unsafe { Guard::new(self, ctx) }
@@ -146,7 +146,7 @@ impl<L: CreatableLock + ?Sized> NeedsLockClass for SeqLock<L> {
146146
}
147147

148148
// SAFETY: The underlying lock ensures mutual exclusion.
149-
unsafe impl<L: CreatableLock + ?Sized> Lock for SeqLock<L> {
149+
unsafe impl<L: CreatableLock + ?Sized> Lock<ReadLock> for SeqLock<L> {
150150
type Inner = L::Inner;
151151
type GuardContext = L::GuardContext;
152152

rust/kernel/sync/spinlock.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//!
77
//! See <https://www.kernel.org/doc/Documentation/locking/spinlocks.txt>.
88
9-
use super::{CreatableLock, GuardMut, Lock};
9+
use super::{CreatableLock, Guard, Lock};
1010
use crate::{bindings, c_types, str::CStr, Opaque};
1111
use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin};
1212

@@ -108,20 +108,20 @@ impl<T> SpinLock<T> {
108108
impl<T: ?Sized> SpinLock<T> {
109109
/// Locks the spinlock and gives the caller access to the data protected by it. Only one thread
110110
/// at a time is allowed to access the protected data.
111-
pub fn lock(&self) -> GuardMut<'_, Self> {
111+
pub fn lock(&self) -> Guard<'_, Self> {
112112
let ctx = self.lock_noguard();
113113
// SAFETY: The spinlock was just acquired.
114-
unsafe { GuardMut::new(self, ctx) }
114+
unsafe { Guard::new(self, ctx) }
115115
}
116116

117117
/// Locks the spinlock and gives the caller access to the data protected by it. Additionally it
118118
/// disables interrupts (if they are enabled).
119119
///
120120
/// When the lock in unlocked, the interrupt state (enabled/disabled) is restored.
121-
pub fn lock_irqdisable(&self) -> GuardMut<'_, Self> {
121+
pub fn lock_irqdisable(&self) -> Guard<'_, Self> {
122122
let ctx = self.internal_lock_irqsave();
123123
// SAFETY: The spinlock was just acquired.
124-
unsafe { GuardMut::new(self, Some(ctx)) }
124+
unsafe { Guard::new(self, Some(ctx)) }
125125
}
126126

127127
fn internal_lock_irqsave(&self) -> c_types::c_ulong {

0 commit comments

Comments
 (0)