Skip to content

Commit 6f56651

Browse files
felipeaggerojeda
authored andcommitted
rust: lock: add trylock method support for lock backend
Add a non-blocking trylock method to lock backend interface, mutex and spinlock implementations. It includes a C helper for spin_trylock. Rust Binder will use this method together with the new shrinker abstractions to avoid deadlocks in the memory shrinker. Link: https://lore.kernel.org/all/[email protected] Signed-off-by: Filipe Xavier <[email protected]> Reviewed-by: Fiona Behrens <[email protected]> Reviewed-by: Alice Ryhl <[email protected]> Reviewed-by: Boqun Feng <[email protected]> Link: https://lore.kernel.org/r/BL0PR02MB4914579914884B5D7473B3D6E96A2@BL0PR02MB4914.namprd02.prod.outlook.com [ Slightly reworded. - Miguel ] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent fae4525 commit 6f56651

File tree

4 files changed

+43
-0
lines changed

4 files changed

+43
-0
lines changed

rust/helpers/spinlock.c

+5
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,8 @@ void rust_helper_spin_unlock(spinlock_t *lock)
2222
{
2323
spin_unlock(lock);
2424
}
25+
26+
int rust_helper_spin_trylock(spinlock_t *lock)
27+
{
28+
return spin_trylock(lock);
29+
}

rust/kernel/sync/lock.rs

+16
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ pub unsafe trait Backend {
5858
#[must_use]
5959
unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState;
6060

61+
/// Tries to acquire the lock.
62+
///
63+
/// # Safety
64+
///
65+
/// Callers must ensure that [`Backend::init`] has been previously called.
66+
unsafe fn try_lock(ptr: *mut Self::State) -> Option<Self::GuardState>;
67+
6168
/// Releases the lock, giving up its ownership.
6269
///
6370
/// # Safety
@@ -128,6 +135,15 @@ impl<T: ?Sized, B: Backend> Lock<T, B> {
128135
// SAFETY: The lock was just acquired.
129136
unsafe { Guard::new(self, state) }
130137
}
138+
139+
/// Tries to acquire the lock.
140+
///
141+
/// Returns a guard that can be used to access the data protected by the lock if successful.
142+
pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
143+
// SAFETY: The constructor of the type calls `init`, so the existence of the object proves
144+
// that `init` was called.
145+
unsafe { B::try_lock(self.state.get()).map(|state| Guard::new(self, state)) }
146+
}
131147
}
132148

133149
/// A lock guard.

rust/kernel/sync/lock/mutex.rs

+11
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,15 @@ unsafe impl super::Backend for MutexBackend {
115115
// caller is the owner of the mutex.
116116
unsafe { bindings::mutex_unlock(ptr) };
117117
}
118+
119+
unsafe fn try_lock(ptr: *mut Self::State) -> Option<Self::GuardState> {
120+
// SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use.
121+
let result = unsafe { bindings::mutex_trylock(ptr) };
122+
123+
if result != 0 {
124+
Some(())
125+
} else {
126+
None
127+
}
128+
}
118129
}

rust/kernel/sync/lock/spinlock.rs

+11
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,15 @@ unsafe impl super::Backend for SpinLockBackend {
114114
// caller is the owner of the spinlock.
115115
unsafe { bindings::spin_unlock(ptr) }
116116
}
117+
118+
unsafe fn try_lock(ptr: *mut Self::State) -> Option<Self::GuardState> {
119+
// SAFETY: The `ptr` pointer is guaranteed to be valid and initialized before use.
120+
let result = unsafe { bindings::spin_trylock(ptr) };
121+
122+
if result != 0 {
123+
Some(())
124+
} else {
125+
None
126+
}
127+
}
117128
}

0 commit comments

Comments
 (0)