[RFC PATCH 8/9] drm/rustgem: implement timeout to prevent hangs
Maíra Canal
mcanal at igalia.com
Fri Mar 17 12:12:12 UTC 2023
In order to prevent possible hangs, if the fence is not signaled for
more than 10 seconds, force the fence to expire by being signaled.
Signed-off-by: Maíra Canal <mcanal at igalia.com>
---
drivers/gpu/drm/rustgem/fence.rs | 31 +++++++++++++++++++++++++++++--
drivers/gpu/drm/rustgem/file.rs | 7 +++++++
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rustgem/fence.rs b/drivers/gpu/drm/rustgem/fence.rs
index 9ef1399548e2..eb1d7faa7e8e 100644
--- a/drivers/gpu/drm/rustgem/fence.rs
+++ b/drivers/gpu/drm/rustgem/fence.rs
@@ -2,10 +2,13 @@
use core::fmt::Write;
use core::ops::Deref;
-use kernel::c_str;
+use core::time::Duration;
use kernel::dma_fence::*;
use kernel::prelude::*;
use kernel::sync::Arc;
+use kernel::time::timer::*;
+use kernel::time::*;
+use kernel::{bindings, c_str, timer_init};
static QUEUE_NAME: &CStr = c_str!("vgem_fence");
static QUEUE_CLASS_KEY: kernel::sync::LockClassKey = kernel::sync::LockClassKey::new();
@@ -36,6 +39,7 @@ impl FenceOps for Fence {
pub(crate) struct VgemFence {
fence: Arc<UniqueFence<Fence>>,
+ _timer: Box<FnTimer<Box<dyn FnMut() -> Result<Next> + Sync>>>,
}
impl VgemFence {
@@ -43,7 +47,30 @@ impl VgemFence {
let fence_ctx = FenceContexts::new(1, QUEUE_NAME, &QUEUE_CLASS_KEY)?;
let fence = Arc::try_new(fence_ctx.new_fence(0, Fence {})?)?;
- Ok(Self { fence })
+ // SAFETY: The caller calls [`FnTimer::init_timer`] before using the timer.
+ let t = Box::try_new(unsafe {
+ FnTimer::new(Box::try_new({
+ let fence = fence.clone();
+ move || {
+ let _ = fence.signal();
+ Ok(Next::Done)
+ }
+ })? as Box<_>)
+ })?;
+
+ // SAFETY: As FnTimer is inside a Box, it won't be moved.
+ let ptr = unsafe { core::pin::Pin::new_unchecked(&*t) };
+
+ timer_init!(ptr, 0, "vgem_timer");
+
+ // SAFETY: Duration.as_millis() returns a valid total number of whole milliseconds.
+ let timeout =
+ unsafe { bindings::msecs_to_jiffies(Duration::from_secs(10).as_millis().try_into()?) };
+
+ // We force the fence to expire within 10s to prevent driver hangs
+ ptr.raw_timer().schedule_at(jiffies_later(timeout));
+
+ Ok(Self { fence, _timer: t })
}
}
diff --git a/drivers/gpu/drm/rustgem/file.rs b/drivers/gpu/drm/rustgem/file.rs
index 2552c7892b0e..a3714e8ca206 100644
--- a/drivers/gpu/drm/rustgem/file.rs
+++ b/drivers/gpu/drm/rustgem/file.rs
@@ -33,6 +33,10 @@ impl File {
/// via the dma-buf reservation object and visible to consumers of the exported
/// dma-buf.
///
+ /// This returns the handle for the new fence that must be signaled within 10
+ /// seconds (or otherwise it will automatically expire). See
+ /// signal (DRM_IOCTL_VGEM_FENCE_SIGNAL).
+ ///
/// If the vGEM handle does not exist, attach returns -ENOENT.
///
pub(crate) fn attach(
@@ -84,6 +88,9 @@ impl File {
/// Signal and consume a fence earlier attached to a vGEM handle using
/// attach (DRM_IOCTL_VGEM_FENCE_ATTACH).
///
+ /// All fences must be signaled within 10s of attachment or otherwise they
+ /// will automatically expire (and signal returns -ETIMEDOUT).
+ ///
/// Signaling a fence indicates to all consumers of the dma-buf that the
/// client has completed the operation associated with the fence, and that the
/// buffer is then ready for consumption.
--
2.39.2
More information about the dri-devel
mailing list