[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260205111635.5307e1fa@fedora>
Date: Thu, 5 Feb 2026 11:16:35 +0100
From: Boris Brezillon <boris.brezillon@...labora.com>
To: Philipp Stanner <phasta@...nel.org>
Cc: David Airlie <airlied@...il.com>, Simona Vetter <simona@...ll.ch>,
Danilo Krummrich <dakr@...nel.org>, Alice Ryhl <aliceryhl@...gle.com>, Gary
Guo <gary@...yguo.net>, Benno Lossin <lossin@...nel.org>, Christian
König <christian.koenig@....com>, Daniel Almeida
<daniel.almeida@...labora.com>, Joel Fernandes <joelagnelf@...dia.com>,
linux-kernel@...r.kernel.org, dri-devel@...ts.freedesktop.org,
rust-for-linux@...r.kernel.org
Subject: Re: [RFC PATCH 2/4] rust: sync: Add dma_fence abstractions
On Tue, 3 Feb 2026 09:14:01 +0100
Philipp Stanner <phasta@...nel.org> wrote:
> +/// A synchronization primitive mainly for GPU drivers.
> +///
> +/// DmaFences are always reference counted. The typical use case is that one side registers
> +/// callbacks on the fence which will perform a certain action (such as queueing work) once the
> +/// other side signals the fence.
> +///
> +/// # Examples
> +///
> +/// ```
> +/// use kernel::sync::{Arc, ArcBorrow, DmaFence, DmaFenceCtx, DmaFenceCb, DmaFenceCbFunc};
> +/// use core::sync::atomic::{self, AtomicBool};
> +///
> +/// static mut CHECKER: AtomicBool = AtomicBool::new(false);
> +///
> +/// struct CallbackData {
> +/// i: u32,
> +/// }
> +///
> +/// impl CallbackData {
> +/// fn new() -> Self {
> +/// Self { i: 9 }
> +/// }
> +/// }
> +///
> +/// impl DmaFenceCbFunc for CallbackData {
> +/// fn callback(cb: Pin<KBox<DmaFenceCb<Self>>>) where Self: Sized {
> +/// assert_eq!(cb.data.i, 9);
> +/// // SAFETY: Just to have an easy way for testing. This cannot race with the checker
> +/// // because the fence signalling callbacks are executed synchronously.
> +/// unsafe { CHECKER.store(true, atomic::Ordering::Relaxed); }
> +/// }
> +/// }
> +///
> +/// struct DriverData {
> +/// i: u32,
> +/// }
> +///
> +/// impl DriverData {
> +/// fn new() -> Self {
> +/// Self { i: 5 }
> +/// }
> +/// }
> +///
> +/// let data = DriverData::new();
> +/// let fctx = DmaFenceCtx::new()?;
> +///
> +/// let mut fence = fctx.as_arc_borrow().new_fence(data)?;
> +///
> +/// let cb_data = CallbackData::new();
> +/// fence.register_callback(cb_data);
> +/// // fence.begin_signalling();
> +/// fence.signal()?;
> +/// // Now check wehether the callback was actually executed.
> +/// // SAFETY: `fence.signal()` above works sequentially. We just check here whether the signalling
> +/// // actually did set the boolean correctly.
> +/// unsafe { assert_eq!(CHECKER.load(atomic::Ordering::Relaxed), true); }
> +///
> +/// Ok::<(), Error>(())
> +/// ```
> +#[pin_data]
> +pub struct DmaFence<T> {
> + /// The actual dma_fence passed to C.
> + #[pin]
> + inner: Opaque<bindings::dma_fence>,
> + /// User data.
> + #[pin]
> + data: T,
A DmaFence is a cross-device synchronization mechanism that can (and
will) cross the driver boundary (one driver can wait on a fence emitted
by a different driver). As such, I don't think embedding a generic T in
the DmaFence and considering it's the object being passed around is
going to work, because, how can one driver know the T chosen by the
driver that created the fence? If you want to have some fence emitter
data attached to the DmaFence allocation, you'll need two kind of
objects:
- one that's type agnostic and on which you can do the callback
registration/unregistration, signalling checks, and generally all
type-agnostic operations. That's basically just a wrapper around a
bindings::dma_fence implementing AlwaysRefCounted.
- one that has the extra data and fctx, with a way to transmute from a
generic fence to a implementer specific one in case the driver wants
to do something special when waiting on its own fences (check done
with the fence ops in C, I don't know how that translates in rust)
> + /// Marks whether the fence is currently in the signalling critical section.
> + signalling: bool,
> + /// A boolean needed for the C backend's lockdep guard.
> + signalling_cookie: bool,
> + /// A reference to the associated [`DmaFenceCtx`] so that it cannot be dropped while there are
> + /// still fences around.
> + fctx: Arc<DmaFenceCtx>,
> +}
Powered by blists - more mailing lists