Skip to content

Commit fbd7a5a

Browse files
Lyudefbq
authored andcommitted
rust: sync: Add lock::Backend::assert_is_held()
Since we've exposed Lock::from_raw() and Guard::new() publically, we want to be able to make sure that we assert that a lock is actually held when constructing a Guard for it to handle instances of unsafe Guard::new() calls outside of our lock module. Hence add a new method assert_is_held() to Backend, which uses lockdep to check whether or not a lock has been acquired. When lockdep is disabled, this has no overhead. [Boqun: Resolve the conflicts with exposing Guard::new(), reword the commit log a bit and format "unsafe { <statement>; }" into "unsafe { <statement> }" for the consistency. ] Signed-off-by: Lyude Paul <lyude@redhat.com> Signed-off-by: Boqun Feng <boqun.feng@gmail.com> Link: https://lore.kernel.org/r/20241125204139.656801-1-lyude@redhat.com
1 parent eb5ccb0 commit fbd7a5a

File tree

5 files changed

+30
-0
lines changed

5 files changed

+30
-0
lines changed

rust/helpers/mutex.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@ void rust_helper___mutex_init(struct mutex *mutex, const char *name,
1212
{
1313
__mutex_init(mutex, name, key);
1414
}
15+
16+
void rust_helper_mutex_assert_is_held(struct mutex *mutex)
17+
{
18+
lockdep_assert_held(mutex);
19+
}

rust/helpers/spinlock.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,8 @@ int rust_helper_spin_trylock(spinlock_t *lock)
3030
{
3131
return spin_trylock(lock);
3232
}
33+
34+
void rust_helper_spin_assert_is_held(spinlock_t *lock)
35+
{
36+
lockdep_assert_held(lock);
37+
}

rust/kernel/sync/lock.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ pub unsafe trait Backend {
9090
// SAFETY: The safety requirements ensure that the lock is initialised.
9191
*guard_state = unsafe { Self::lock(ptr) };
9292
}
93+
94+
/// Asserts that the lock is held using lockdep.
95+
///
96+
/// # Safety
97+
///
98+
/// Callers must ensure that [`Backend::init`] has been previously called.
99+
unsafe fn assert_is_held(ptr: *mut Self::State);
93100
}
94101

95102
/// A mutual exclusion primitive.
@@ -235,6 +242,9 @@ impl<'a, T: ?Sized, B: Backend> Guard<'a, T, B> {
235242
///
236243
/// The caller must ensure that it owns the lock.
237244
pub unsafe fn new(lock: &'a Lock<T, B>, state: B::GuardState) -> Self {
245+
// SAFETY: The caller can only hold the lock if `Backend::init` has already been called.
246+
unsafe { B::assert_is_held(lock.state.get()) };
247+
238248
Self {
239249
lock,
240250
state,

rust/kernel/sync/lock/mutex.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,9 @@ unsafe impl super::Backend for MutexBackend {
134134
None
135135
}
136136
}
137+
138+
unsafe fn assert_is_held(ptr: *mut Self::State) {
139+
// SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use.
140+
unsafe { bindings::mutex_assert_is_held(ptr) }
141+
}
137142
}

rust/kernel/sync/lock/spinlock.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,9 @@ unsafe impl super::Backend for SpinLockBackend {
133133
None
134134
}
135135
}
136+
137+
unsafe fn assert_is_held(ptr: *mut Self::State) {
138+
// SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use.
139+
unsafe { bindings::spin_assert_is_held(ptr) }
140+
}
136141
}

0 commit comments

Comments
 (0)