Skip to content

Commit 1f4c815

Browse files
committed
rust: device: Add support for locking the device
Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 9f46328 commit 1f4c815

2 files changed

Lines changed: 40 additions & 1 deletion

File tree

rust/helpers/device.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,13 @@ int rust_helper_devm_add_action(struct device *dev,
88
{
99
return devm_add_action(dev, action, data);
1010
}
11+
12+
void rust_helper_device_lock(struct device *dev)
13+
{
14+
device_lock(dev);
15+
}
16+
17+
void rust_helper_device_unlock(struct device *dev)
18+
{
19+
device_unlock(dev);
20+
}

rust/kernel/device.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
bindings,
99
error::{Error, Result},
1010
str::CStr,
11-
types::{ARef, Opaque},
11+
types::{ARef, NotThreadSafe, Opaque},
1212
};
1313
use core::{fmt, marker::PhantomData, ptr};
1414

@@ -256,6 +256,35 @@ impl<Ctx: DeviceContext> Device<Ctx> {
256256
// SAFETY: By the invariant of `CStr`, `name` is null-terminated.
257257
unsafe { bindings::device_property_present(self.as_raw().cast_const(), name.as_char_ptr()) }
258258
}
259+
260+
/// Locks the [`Device`] for exclusive access.
261+
pub fn lock(&self) -> Guard<'_, Ctx> {
262+
// SAFETY: `self` is always valid by the type invariant.
263+
unsafe { bindings::device_lock(self.as_raw()) };
264+
265+
Guard {
266+
dev: self,
267+
_not_send: NotThreadSafe,
268+
}
269+
}
270+
}
271+
272+
/// A lock guard.
273+
///
274+
/// The lock is unlocked when the guard goes out of scope.
275+
#[must_use = "the lock unlocks immediately when the guard is unused"]
276+
pub struct Guard<'a, Ctx: DeviceContext = Normal> {
277+
dev: &'a Device<Ctx>,
278+
_not_send: NotThreadSafe,
279+
}
280+
281+
impl<Ctx: DeviceContext> Drop for Guard<'_, Ctx> {
282+
fn drop(&mut self) {
283+
// SAFETY:
284+
// - `self.xa.xa` is always valid by the type invariant.
285+
// - The caller holds the lock, so it is safe to unlock it.
286+
unsafe { bindings::device_unlock(self.dev.as_raw()) };
287+
}
259288
}
260289

261290
// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic

0 commit comments

Comments
 (0)