Skip to content

Commit 3bfa894

Browse files
committed
rust: device: Add support for locking the device
Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 77bf1d9 commit 3bfa894

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

rust/helpers/device.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,13 @@ void rust_helper_dev_set_drvdata(struct device *dev, void *data)
2525
{
2626
dev_set_drvdata(dev, data);
2727
}
28+
29+
void rust_helper_device_lock(struct device *dev)
30+
{
31+
device_lock(dev);
32+
}
33+
34+
void rust_helper_device_unlock(struct device *dev)
35+
{
36+
device_unlock(dev);
37+
}

rust/kernel/device.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use core::{any::TypeId, marker::PhantomData, ptr};
1515
#[cfg(CONFIG_PRINTK)]
1616
use crate::c_str;
1717

18+
use crate::types::NotThreadSafe;
19+
1820
pub mod property;
1921

2022
// Assert that we can `read()` / `write()` a `TypeId` instance from / into `struct driver_type`.
@@ -484,6 +486,35 @@ impl<Ctx: DeviceContext> Device<Ctx> {
484486
// defined as a `#[repr(transparent)]` wrapper around `fwnode_handle`.
485487
Some(unsafe { &*fwnode_handle.cast() })
486488
}
489+
490+
/// Locks the [`Device`] for exclusive access.
491+
pub fn lock(&self) -> Guard<'_, Ctx> {
492+
// SAFETY: `self` is always valid by the type invariant.
493+
unsafe { bindings::device_lock(self.as_raw()) };
494+
495+
Guard {
496+
dev: self,
497+
_not_send: NotThreadSafe,
498+
}
499+
}
500+
}
501+
502+
/// A lock guard.
503+
///
504+
/// The lock is unlocked when the guard goes out of scope.
505+
#[must_use = "the lock unlocks immediately when the guard is unused"]
506+
pub struct Guard<'a, Ctx: DeviceContext = Normal> {
507+
dev: &'a Device<Ctx>,
508+
_not_send: NotThreadSafe,
509+
}
510+
511+
impl<Ctx: DeviceContext> Drop for Guard<'_, Ctx> {
512+
fn drop(&mut self) {
513+
// SAFETY:
514+
// - `self.xa.xa` is always valid by the type invariant.
515+
// - The caller holds the lock, so it is safe to unlock it.
516+
unsafe { bindings::device_unlock(self.dev.as_raw()) };
517+
}
487518
}
488519

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

0 commit comments

Comments
 (0)