Powerful Spells Caster Spiritual Healer
Web: https://nativewitchspells.com/
Text: +256759011277
Phone Call: +256793306060
Email: bbaantu(a)gmail.com
Lottery gambling spells to win lots of money at the lotto jackpot. Get the lotto winning numbers using lottery winning spells to increase your chances of winning. Attract good luck when gambling, increase your chances of winning & enhance your psychic powers when gambling using my good luck lottery winning spells that work.
Lottery spells to change your luck at the lottery; lottery luck spells to change your mathematical mind set using numerology to predict accurately the lotto winning numbers. Good luck lotto spells to change your spiritual mind set to make it possible for you to win million in the lottery. Unlimited winnings using good luck lotto spells. If you want a gambling spell to neutralize and cancel out any spells and hexes against your gambling success, then get one of my powerful gambling rival gambling spells.
Lotto spells that work to draw money towards you when playing the lottery. Stop losing money and make millions from the lottery with lotto spells that work fast. Choose this lotto money spell to receive a large sum of money at the lottery or make someone else receive a large sum of money at the lottery. Win bigger prizes from the lotto with lottery spells that will work in any country. Learn how to increase your chances of winning the lottery with lotto spells. This lotto spell advantage is priceless when playing lotto or gambling as the lottery spells that work fast will work to bring luck, positive energy and winnings.
Lottery spells to change your luck at the lottery, lottery luck spells to change your mathematical logic using numerology to predict accurately the lotto winning numbers and lotto spells that work to change your spiritual conception to make it possible for you to win million in the lottery.
Lottery spells, sports betting spells, horse betting spells, casino money spells, spells to win the lottery jackpot, gambling spells. Get large sums of money at the lottery with lottery luck spells. Draw money towards you when gambling at the casino with casino gambling spells.
Bring the odds of winning in your favour with gambling spells for luck & positive energy. Lotto spells to win the lottery by increasing your psychic powers.
You can call Chief Bweza +256793306060 / +256759011277
bbaantu(a)gmail.com
THE BEST AND LEGITIMATE HACKER IN THE WORLD // GEO COORDINATES RECOVERY HACKER
Do you want to hire a hacker to solve your problems in various conditions? If you require the services of a genuine hacker and do not have any idea about how to hire a professional hacker online, you are at the right place. There are many cryptocurrency theft cases and schemes currently in circulation in the whole world so it’s important to be careful before investing with any platform. I lost almost all my savings in a fake investment website but I got rescued through the recovery hacker called GEO COORDINATES RECOVERY HACKER as they recovered my stolen funds completely without hassle or hidden fees. This expert retrieved my stolen funds remotely within a few hours as I got notification on my blockchain wallet my funds had been restored. This is the best help I ever got on the internet and I decided to give them a good review about their good job and how quick they are in helping and standing for individuals in tough situations. Kindly contact them if you are in trouble.
Email: geovcoordinateshacker(a)gmail.com
Website; https://geovcoordinateshac.wixsite.com/geo-coordinates-hack
WhatsApp: +1 ( 318 ) 203-3657 )
Manhood Specialist
https://nativewitchspells.com/
WhatsApp: +256759011277
Calls: +256793306060
Email: bbaantu(a)gmail.com
Free Fast Delivery
Manhood Enlargement Premature Ejaculation Weak Erection Treatments
if you are looking for an herbal sexual enhancer to boost your performance to levels that you have never experienced before
It makes perfect sense to get the best and 100%natural strong one
Supercharge will help you to perform when you need to.
These are formulated to give you harder, stronger and more frequent erections and will supercharge your sexual libido
there are no side effects known to occur from this supplement.
With No Side Effects 100% Herbal Creams, Pills, Pumps, Booster and Capsules for
WhatsApp: +256759011277
https://nativewitchspells.com/men-clinic/
Calls: +256793306060
Email: bbaantu(a)gmail.com
Bigger, harder and more frequent erections.
Enhanced desire, power, pleasure and performance.
Massively intense and electrifying orgasms.
Increased endurance for longer lasting sessions.
Easier and more reliable sexual response.
Enhance male pleasure and performance with this reliable men's product.
Improve your overall sex life.
Same day results 100% Herbal No Side Effects
Traditional herbal remedies used in the management of sexual impotence and erectile dysfunction
1. For erection (Strengthen)
2. For premature ejaculation (To prolong sexual intercourse)
3. For erection + For premature ejaculation (2 in 1)
- Improves blood circulation
- Eliminates erectile dysfunction
- Provides more control and satisfaction
- Maximally prolongs sexual intercourse
- Delays ejaculation
- Increases sperm volume
- Intensifies satisfaction
- Increases arousal level
Male Low Libido.
Male Impotence.
Laziness in the Bed.
Premature Ejaculation.
Cannot Satisfy Your Partner.
Or Any other Sexual Concern.
WhatsApp: +256759011277
Calls: +256793306060
Email: bbaantu(a)gmail.com
https://nativewitchspells.com/men-clinic/
Same Day Results
On Wed Aug 5, 2026 at 3:59 PM BST, Philipp Stanner wrote:
> From: Danilo Krummrich <dakr(a)kernel.org>
>
> Implement ForeignOwnable for ARef<T>, making it possible for C code to
> own an ARef<T>.
>
> Since ARef represents shared ownership, BorrowedMut is &T rather than
> &mut T, matching the semantics of the underlying reference-counted type.
>
> Signed-off-by: Danilo Krummrich <dakr(a)kernel.org>
> Reviewed-by: Alice Ryhl <aliceryhl(a)google.com>
> Tested-by: Daniel Almeida <daniel.almeida(a)collabora.com>
> ---
> rust/kernel/sync/aref.rs | 40 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 40 insertions(+)
>
> diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs
> index b721b2e00b98..540766613659 100644
> --- a/rust/kernel/sync/aref.rs
> +++ b/rust/kernel/sync/aref.rs
> @@ -24,6 +24,11 @@
> ptr::NonNull, //
> };
>
> +use crate::{
> + prelude::*,
> + types::ForeignOwnable, //
> +};
> +
> /// Types that are _always_ reference counted.
> ///
> /// It allows such types to define their own custom ref increment and decrement functions.
> @@ -188,6 +193,41 @@ fn eq(&self, other: &ARef<U>) -> bool {
> }
> impl<T: AlwaysRefCounted + Eq> Eq for ARef<T> {}
>
> +// SAFETY: `into_foreign` returns a pointer from `NonNull::as_ptr`, so it's non-null. The
> +// `ARef` invariant guarantees that `ptr` points to a valid `T`, so it's aligned to `T`.
> +unsafe impl<T: AlwaysRefCounted + 'static> ForeignOwnable for ARef<T> {
> + const FOREIGN_ALIGN: usize = core::mem::align_of::<T>();
> +
> + type Borrowed<'a> = &'a T;
> + type BorrowedMut<'a> = &'a T;
> +
`#[inline]` here and all others.
Best,
Gary
> + fn into_foreign(self) -> *mut c_void {
> + ARef::into_raw(self).as_ptr().cast()
> + }
> +
> + unsafe fn from_foreign(ptr: *mut c_void) -> Self {
> + // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
> + // call to `Self::into_foreign`.
> + let ptr = unsafe { NonNull::new_unchecked(ptr.cast()) };
> +
> + // SAFETY: `ptr` came from `into_foreign`, which consumed an `ARef` without decrementing
> + // the refcount, so we can transfer the ownership to the new `ARef`.
> + unsafe { ARef::from_raw(ptr) }
> + }
> +
> + unsafe fn borrow<'a>(ptr: *mut c_void) -> &'a T {
> + // SAFETY: The safety requirements of this method ensure that the object remains alive and
> + // immutable for the duration of 'a.
> + unsafe { &*ptr.cast() }
> + }
> +
> + unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> &'a T {
> + // SAFETY: The safety requirements for `borrow_mut` are a superset of the safety
> + // requirements for `borrow`.
> + unsafe { <Self as ForeignOwnable>::borrow(ptr) }
> + }
> +}
> +
> impl<T, U> PartialEq<&'_ U> for ARef<T>
> where
> T: AlwaysRefCounted + PartialEq<U>,
On Wed Aug 5, 2026 at 3:59 PM BST, Philipp Stanner wrote:
> C's dma_fence's are synchronisation primitives that will be needed by all
> Rust GPU drivers.
>
> The dma_fence framework sets a number of rules, notably:
> - fences must only be signaled once
> - all fences must be signaled at some point
> - fence error codes must only be set before signaling
> - every pointer to a fence must be backed by a reference
>
> All those rules are being addressed by these abstractions.
>
> To cleanly decouple fence issuers and consumers, two types are provided:
> - DriverFence: the only fence type that can be signaled and that
> carries driver-specific data.
> - Fence: the fence type to be shared with other drivers and / or
> userspace. The only type callbacks can be registered on.
> Cannot be signaled.
>
> Hereby, a Fence lives in the same chunk of memory as a DriverFence. Both
> share the refcount of the underlying C dma_fence. Since this
> implementation does not provide a custom dma_fence_backend_ops.release()
> function, the memory is freed by the dma_fence backend once the refcount
> drops to 0.
>
> To create a DriverFence, the user must first allocate a
> DriverFenceAllocation, so that the creation of the DriverFence later on
> can always succeed. Otherwise, deadlocks could occur if fences need to
> be created in a GPU job submission path.
>
> Synchronization is ensured by the dma_fence backend.
>
> All DriverFence's created through this abstraction must be signaled by
> the creator with an error code. In case a DriverFence drops without
> being signaled beforehand, it is signaled with -ECANCELLED as its
> error and a warning is printed. This allows the Rust abstraction to very
> cleanly decouple fence issuer and consumer by relying on the decoupling
> mechanisms in the C backend, which ensures through RCU and the
> 'signaled' fence-flag that dma_fence_backend_ops functions cannot
> access the potentially unloaded driver code anymore.
>
> Signalling fences on drop thus grants many advantages. Not signaling
> fences on drop would risk deadlock and does not grant real advantages:
> By definition only the drivers can ensure that a fence always represents
> the hardware's state correctly.
>
> This implementation models a DmaFenceContext object on which fences are
> to be created, thereby ensuring correct sequence numbering according to
> the timeline.
>
> dma_fence supports a variety of callbacks. The mandatory callbacks
> (get_timeline_name() and get_driver_name()) are implemented in this
> patch. For convenience, they store those name parameters in the fence
> context, saving the driver from implementing these two callbacks.
>
> Support for other callbacks (like for hardware signaling) is prepared
> for through the fact that both DriverFence and Fence live in the same
> allocation, allowing for usage of container_of from the callback to
> access the driver-specific data.
>
> It is expected that other callbacks, added in the future, also mostly
> operate on the generic data in the FenceContext. To make this safe, the
> implementation ensures through a lifetime that a DriverFence cannot
> outlive its FenceContext.
>
> Synchronization for dma_fence_ops callbacks is ensured by only running the
> Rust deconstructor delayed with call_rcu(), which prevents UAF-bugs
> should a DriverFence drop while a Fence callback is currently operating
> on the associated driver data. Since they can also operate on the
> FenceContext's data, its drop implementation also performs the necessary
> delay with rcu_barrier().
>
> An additional issue discovered during the review process of this code is
> that there is (currently) no mechanism in Rust to prevent someone from
> circumventing the DriverFence's FenceContext-reference's lifetime by
> "forgetting" the fence, e.g. with core::mem::forget(). This would enable
> UAF bugs on the FenceContext. Throw a panic if this happens and document
> a path towards a more robust solution.
>
> Add abstractions for dma_fence in Rust.
>
> Signed-off-by: Philipp Stanner <phasta(a)kernel.org>
> Tested-by: Daniel Almeida <daniel.almeida(a)collabora.com>
> ---
> rust/bindings/bindings_helper.h | 1 +
> rust/helpers/dma_fence.c | 48 ++
> rust/helpers/helpers.c | 1 +
> rust/kernel/dma_buf/dma_fence.rs | 1002 ++++++++++++++++++++++++++++++
> rust/kernel/dma_buf/mod.rs | 14 +
> rust/kernel/lib.rs | 1 +
> 6 files changed, 1067 insertions(+)
> create mode 100644 rust/helpers/dma_fence.c
> create mode 100644 rust/kernel/dma_buf/dma_fence.rs
> create mode 100644 rust/kernel/dma_buf/mod.rs
>
> diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
> index 1124785e210b..54b62d952e01 100644
> --- a/rust/bindings/bindings_helper.h
> +++ b/rust/bindings/bindings_helper.h
> @@ -53,6 +53,7 @@
> #include <linux/debugfs.h>
> #include <linux/device/faux.h>
> #include <linux/dma-direction.h>
> +#include <linux/dma-fence.h>
> #include <linux/dma-mapping.h>
> #include <linux/dma-resv.h>
> #include <linux/errname.h>
> diff --git a/rust/helpers/dma_fence.c b/rust/helpers/dma_fence.c
> new file mode 100644
> index 000000000000..0e08411098fa
> --- /dev/null
> +++ b/rust/helpers/dma_fence.c
> @@ -0,0 +1,48 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/dma-fence.h>
> +
> +__rust_helper void rust_helper_dma_fence_get(struct dma_fence *f)
> +{
> + dma_fence_get(f);
> +}
> +
> +__rust_helper void rust_helper_dma_fence_put(struct dma_fence *f)
> +{
> + dma_fence_put(f);
> +}
> +
> +__rust_helper bool rust_helper_dma_fence_begin_signalling(void)
> +{
> + return dma_fence_begin_signalling();
> +}
> +
> +__rust_helper void rust_helper_dma_fence_end_signalling(bool cookie)
> +{
> + dma_fence_end_signalling(cookie);
> +}
> +
> +__rust_helper bool rust_helper_dma_fence_is_signaled(struct dma_fence *f)
> +{
> + return dma_fence_is_signaled(f);
> +}
> +
> +__rust_helper bool rust_helper_dma_fence_test_signaled_flag(struct dma_fence *f)
> +{
> + return dma_fence_test_signaled_flag(f);
> +}
> +
> +__rust_helper void rust_helper_dma_fence_lock_irqsave(struct dma_fence *f, unsigned long *flags)
> +{
> + dma_fence_lock_irqsave(f, *flags);
> +}
> +
> +__rust_helper void rust_helper_dma_fence_unlock_irqrestore(struct dma_fence *f, unsigned long *flags)
> +{
> + dma_fence_unlock_irqrestore(f, *flags);
> +}
> +
> +__rust_helper void rust_helper_dma_fence_set_error(struct dma_fence *f, int error)
> +{
> + dma_fence_set_error(f, error);
> +}
> diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
> index 998e31052e66..4ab8aa9da7e7 100644
> --- a/rust/helpers/helpers.c
> +++ b/rust/helpers/helpers.c
> @@ -58,6 +58,7 @@
> #include "cred.c"
> #include "device.c"
> #include "dma.c"
> +#include "dma_fence.c"
> #include "dma-resv.c"
> #include "drm.c"
> #include "drm_gpuvm.c"
> diff --git a/rust/kernel/dma_buf/dma_fence.rs b/rust/kernel/dma_buf/dma_fence.rs
> new file mode 100644
> index 000000000000..e61b4b2d8b8c
> --- /dev/null
> +++ b/rust/kernel/dma_buf/dma_fence.rs
> @@ -0,0 +1,1002 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2025-2026 Red Hat Inc.
> + * Author: Philipp Stanner <pstanner(a)redhat.com>
> + */
> +
> +//! DriverFence support.
> +//!
> +//! Reference: <https://docs.kernel.org/driver-api/dma-buf.html#c.dma_fence>
> +//!
> +//! header: [`include/linux/dma-fence.h`](srctree/include/linux/dma-fence.h)
> +
> +use crate::{
> + alloc::AllocError,
> + bindings,
> + container_of,
> + error::to_result,
> + prelude::*,
> + types::ForeignOwnable,
> + types::Opaque, //
> +};
> +
> +use core::{
> + marker::PhantomData,
> + mem::ManuallyDrop,
> + ops::Deref,
> + ptr,
> + ptr::{
> + drop_in_place,
> + NonNull, //
> + }, //
> +};
> +
> +use kernel::{
> + str::CString,
> + sync::{
> + aref::{
> + ARef,
> + AlwaysRefCounted, //
> + },
> + atomic::{
> + Atomic,
> + Relaxed, //
> + },
> + rcu::rcu_barrier, //
> + }, //
> +};
> +
> +/// VTable for dma_fence backend_ops callbacks.
> +//
> +// Mandatory dma_fence backend_ops are implemented implicitly through
> +// [`FenceContext`]. Additional ones shall get implemented on this trait.
> +pub trait FenceContextOps {
> + /// The generic payload data for [`DriverFence`]s created on this fctx.
> + type FenceDataType: Send + Sync;
> +}
> +
> +/// A dma-fence context. A fence context takes care of associating related fences
> +/// with each other, providing each with raising sequence numbers and a common
> +/// identifier.
> +#[pin_data(PinnedDrop)]
> +pub struct FenceContext<T: FenceContextOps + Send + Sync> {
> + /// The fence context number.
> + nr: u64,
> + /// The sequence number for the next fence created.
> + seqno: Atomic<u64>,
> + // The name parameters can be accessed by the dma_fence backend_ops. UAF
> + // errors are prevented by the `call_rcu()` in `drop_driver_fence_data()`.
> + /// The name of the driver this FenceContext's fences belong to.
> + driver_name: CString,
> + /// The name of the timeline this FenceContext's fences belong to.
> + timeline_name: CString,
> + /// The number of all unsignaled fences on this context.
> + // Used to prevent bugs due to forgotten fences.
> + //
> + // The lifetime on `DriverFence`s should typically prevent this from
> + // happening.
> + //
> + // However, we cannot fully guarantee in Rust that `DriverFence`s will not
> + // be forgotten, e.g., through `core::mem::forget()`. This could circumvent
> + // the lifetime which intends to enforce that all fences disappear before
> + // their context.
> + nr_of_unsignaled_fences: Atomic<u64>,
This can be `Atomic<usize>` so it doesn't need to go through the generic 64-bit
atomic mechanism on 32-bit systems.
> + /// The user's data.
> + #[pin]
> + data: T,
> +}
> +
> +impl<'a, T: Send + Sync + FenceContextOps> FenceContext<T> {
> + // This can later be extended as a vtable in case other parties need support
> + // for the more "exotic" callbacks.
> + const OPS: bindings::dma_fence_ops = bindings::dma_fence_ops {
> + get_driver_name: Some(Self::get_driver_name),
> + get_timeline_name: Some(Self::get_timeline_name),
> + enable_signaling: None,
> + signaled: None,
> + wait: None,
> + release: None,
> + set_deadline: None,
> + };
> +
> + /// Create a new `FenceContext`.
> + pub fn new<E>(
> + initial_seqno: u64,
> + driver_name: CString,
> + timeline_name: CString,
> + data: impl PinInit<T, E>,
> + ) -> impl PinInit<Self, Error>
> + where
> + Error: From<E>,
> + {
> + try_pin_init!(Self {
> + // SAFETY: `dma_fence_context_alloc()` merely works on a global
> + // atomic. Parameter `1` is the number of contexts we want to
> + // allocate.
> + nr: unsafe { bindings::dma_fence_context_alloc(1) },
> + seqno: Atomic::new(initial_seqno),
> + driver_name,
> + timeline_name,
> + nr_of_unsignaled_fences: Atomic::new(0),
> + data <- data,
> + })
> + }
> +
> + fn next_seqno(&self) -> u64 {
> + self.seqno.fetch_add(1, Relaxed)
> + }
> +
> + /// Allocate the memory for a [`DriverFence`] and already store `data` inside.
> + ///
> + /// This is needed because many times, creation of a [`DriverFence`] must not
> + /// fail, and allocating might deadlock in some situations.
> + ///
> + /// The `data` you pass here must not perform any operations that are illegal
> + /// in atomic context in its [`Drop`] implementation.
> + pub fn new_fence_allocation(
> + &self,
> + data: T::FenceDataType,
> + ) -> Result<DriverFenceAllocation<'_, T>> {
> + let fence_data = DriverFenceData {
> + rcu_head: Default::default(),
> + // `inner` remains uninitialized until a `DriverFence` takes over.
> + inner: Fence {
> + inner: Opaque::uninit(),
> + },
> + fctx: self,
> + data,
> + };
> +
> + // In order to support the C dma_fence callbacks, it is necessary for
> + // a `Fence` and a `DriverFence` to live in the same allocation,
> + // because the C backend passes a dma_fence, from which the driver most
> + // likely wants to be able to access its `data` in `DriverFence`.
> + //
> + // Hence, we need the manage the memory manually. It will be freed by the
> + // C backend automatically once the refcount within `Fence` drops to 0.
> + let data = KBox::new(fence_data, GFP_KERNEL | __GFP_ZERO)?;
> +
> + Ok(DriverFenceAllocation {
> + data,
> + ops: &Self::OPS,
> + })
> + }
> +
> + extern "C" fn get_driver_name(ptr: *mut bindings::dma_fence) -> *const c_char {
> + // SAFETY: The C backend only invokes this callback with `ptr` pointing
> + // to a valid, unsignaled `bindings::dma_fence`. All fences created in
> + // this module always reside within `Fence` which always resides in a
> + // `DriverFenceData`, thus satisfying the function's safety
> + // requirements.
> + let fctx = unsafe { Self::from_raw_fence(ptr) };
> +
> + fctx.driver_name.as_char_ptr()
> + }
> +
> + extern "C" fn get_timeline_name(ptr: *mut bindings::dma_fence) -> *const c_char {
> + // SAFETY: The C backend only invokes this callback with `ptr` pointing
> + // to a valid, unsignaled `bindings::dma_fence`. All fences created in
> + // this module always reside within `Fence` which always resides in a
> + // `DriverFenceData`, thus satisfying the function's safety
> + // requirements.
> + let fctx = unsafe { Self::from_raw_fence(ptr) };
> +
> + fctx.timeline_name.as_char_ptr()
> + }
> +
> + /// Create a [`FenceContext`] from an associated [`bindings::dma_fence`].
> + ///
> + /// # Safety
> + ///
> + /// `ptr` must be a valid pointer to a [`bindings::dma_fence`] which resides
> + /// within a [`Fence`], which in turn resides in a [`DriverFenceData`].
> + unsafe fn from_raw_fence(ptr: *mut bindings::dma_fence) -> &'a Self {
> + let opaque_fence = Opaque::cast_from(ptr);
> +
> + // SAFETY: Safe due to the function's overall safety requirements.
> + let fence_ptr = unsafe { container_of!(opaque_fence, Fence, inner) };
> +
> + // CAST: `DriverFenceData` is repr(C) and a `Fence` is its first member.
`repr(C)`
> + let fence_data_ptr = fence_ptr as *mut DriverFenceData<'a, T>;
`*const` should work here too?
> +
> + // SAFETY: Safe because of the comments directly above.
> + let fence_data = unsafe { &*fence_data_ptr };
> +
> + fence_data.fctx
> + }
> +}
> +
> +// FenceContext's drop() ensures that the driver cannot unload while there are
> +// still dma_fence callbacks running. This also prevents UAF problems with
> +// `fctx.driver_name` and `fctx.timeline_name`.
> +//
> +// DriverFence data gets dropped through `call_rcu()` in `DriverFence::drop`.
> +// This `rcu_barrier()` also serves to wait for their completion.
These should be comment on the drop code itself, not as comment of `PinnedDrop`
impl.
This can be more detailed about why a UAF problem exists (and this should be
commented on the panic part, as something like:
// Fence ops callbacks may be called on unsignaled fences, so we may not
// leak any driver fences, otherwise `fctx.driver_name` and
// `fctx.timeline_name` can be accessed after drop (UAF).
if self.nr_of_unsignaled_fences.load(Relaxed) != 0 {
// Fence ops callbacks use RCU to sychronize callbacks and thus we use `call_rcu`
// to destroy `DriverFence` data. `rcu_barrier` here synchronize with driver
// fence's destruction.
> +#[pinned_drop]
> +impl<T: FenceContextOps + Send + Sync> PinnedDrop for FenceContext<T> {
> + fn drop(self: Pin<&mut Self>) {
> + // TODO:
> + // It would be better if the fence context signals all forgotten fences
> + // itself. To do so, it would keep a list of unsignaled fences. That
> + // list members would have to be pre-allocated (see
> + // `FenceCallback::new_fence_allocation()`).
> + if self.nr_of_unsignaled_fences.load(Relaxed) != 0 {
> + panic!("Forgotten fences in FenceContext.");
> + }
> +
> + rcu_barrier();
> + }
> +}
> +
> +/// Error type for fence callback registration.
> +///
> +/// Generic over `T` so that `AlreadySignaled` can return the callback to the
> +/// caller, allowing it to reclaim any resources owned by the callback (e.g.,
> +/// a fence handle that needs to be signaled).
> +#[derive(Debug)]
> +pub enum CallbackError<T = ()> {
What is this `= ()` used for?
> + /// The fence was already signaled. The callback is returned so the caller
> + /// can extract owned resources without losing them.
> + AlreadySignaled(T),
> + /// Some other error occurred during registration.
> + Other(Error),
> +}
> +
> +impl<T> From<CallbackError<T>> for Error {
#[inline]
> + fn from(err: CallbackError<T>) -> Self {
> + match err {
> + CallbackError::AlreadySignaled(_) => ENOENT,
> + CallbackError::Other(e) => e,
> + }
> + }
> +}
> +
> +impl<T> From<AllocError> for CallbackError<T> {
#[inline]
> + fn from(e: AllocError) -> Self {
> + CallbackError::Other(Error::from(e))
> + }
> +}
> +
> +/// Trait for callbacks that can be registered on fences.
> +///
> +/// When the fence signals, the callback will be invoked.
> +///
> +/// # Example
> +///
> +/// ```rust
> +/// use kernel::dma_buf::FenceCallback;
> +///
> +/// struct MyCallback {
> +/// // Your callback state here
> +/// }
> +///
> +/// impl FenceCallback for MyCallback {
> +/// fn called(&mut self) {
> +/// pr_info!("Fence signaled!");
> +/// // Handle fence completion
> +/// }
> +/// }
> +/// ```
> +pub trait FenceCallback: Send + 'static {
> + /// Called when the fence is signaled.
> + ///
> + /// This is called from the fence signaling path, which may be in interrupt
> + /// context or with locks held, which is why `self` is only borrowed, so that
> + /// it cannot drop. Implementations must not sleep or perform
> + /// long-running operations.
> + ///
> + /// An implementation likely wants to inform itself (e.g., through a work item)
> + /// within this callback that the associated [`FenceCallbackRegistration`]
> + /// can now be dropped.
> + fn called(&mut self);
The name feels a bit awkward to me. I think this should either look like an
action on the callback, in which case "call" or describe an event on the fence,
i.e. "on_signal" or "signaled". Naming it "called" is very weird because it's
not a event that is triggered when something is "called".
> +}
> +
> +/// A callback registration on a fence.
> +///
> +/// When this object is dropped, the callback is automatically removed if it
> +/// hasn't been called yet.
> +#[pin_data(PinnedDrop)]
> +pub struct FenceCallbackRegistration<T: FenceCallback + 'static> {
> + #[pin]
> + callback_foreign: Opaque<bindings::dma_fence_cb>,
> + callback: ManuallyDrop<T>,
> + fence: ARef<Fence>,
> +}
> +
> +impl<T: FenceCallback> FenceCallbackRegistration<T> {
> + /// Create a [`PinInit`] closure for registering a callback on a fence.
> + ///
> + /// The actual attempt at registering the callback will take place once you
> + /// call an allocator's `pin_init()` function.
> + ///
> + /// On success the callback is pinned in place and will fire when the fence
> + /// signals. On `AlreadySignaled` the callback is returned to the caller so
> + /// that owned resources can be reclaimed.
> + pub fn new<'a>(fence: &'a Fence, callback: T) -> impl PinInit<Self, CallbackError<T>> + 'a
> + where
> + T: 'a,
> + {
> + try_pin_init!(Self {
> + // We need to fully initialize the fence because after
> + // `dma_fence_add_callback()` ran, the callback might immediately
> + // get invoked.
> + callback: ManuallyDrop::new(callback),
> + fence: ARef::from(fence),
> + callback_foreign <- Opaque::try_ffi_init(|ptr| {
> + // SAFETY: `fence.inner.get()` is a valid, initialized `struct
> + // dma_fence`. `ptr` points to the `struct dma_fence_cb` field
> + // within the pinned allocation, so it remains valid until
> + // `dma_fence_remove_callback()` in `PinnedDrop` or until the
> + // callback fires.
> + let ret = unsafe {
> + to_result(bindings::dma_fence_add_callback(
> + fence.inner.get(),
> + ptr,
> + Some(Self::dma_fence_callback),
> + ))
> + };
> + match ret {
> + Ok(()) => Ok(()),
> + Err(e) => {
> + // SAFETY: We could not register the callback. Thus,
> + // C will not use it. So we can just take it back
> + // and pass it to the user again.
> + let cb_back = unsafe { ManuallyDrop::take(callback) };
> + if e == ENOENT {
> + Err(CallbackError::AlreadySignaled(cb_back))
> + } else {
> + Err(CallbackError::Other(e))
> + }
> + },
> + }
> + }),
> + }? CallbackError<T>)
> + }
> +
> + /// Raw dma fence callback that is called by the C code.
> + ///
> + /// # Safety
> + ///
> + /// This is only called by the dma_fence subsystem with valid pointers.
> + unsafe extern "C" fn dma_fence_callback(
> + _fence: *mut bindings::dma_fence,
> + callback_foreign: *mut bindings::dma_fence_cb,
> + ) {
> + let ptr = Opaque::cast_from(callback_foreign).cast_mut();
> +
> + // SAFETY: All `cb` we can receive here have been created in such a way
> + // that they are embedded into a `FenceCallbackRegistration`. The
> + // backend ensures synchronisation so whoever holds the registration
> + // object cannot drop it while this code is running. See
> + // `FenceCallbackRegistration::drop`.
> + unsafe {
> + let reg: *mut Self = container_of!(ptr, Self, callback_foreign);
> +
> + (*reg).callback.called();
> + }
> + }
> +
> + /// Returns a reference to the fence this callback is registered on.
> + pub fn fence(self: Pin<&Self>) -> &Fence {
> + &self.get_ref().fence
> + }
This can just be `fence(&self) -> &Fence`.
> +}
> +
> +#[pinned_drop]
> +impl<T: FenceCallback> PinnedDrop for FenceCallbackRegistration<T> {
> + fn drop(self: Pin<&mut Self>) {
> + // Always call dma_fence_remove_callback, even if `callback` has already
> + // been taken by `dma_fence_callback`. This is necessary for
Is this still up-to-date? You're not taking callback anymore in
`dma_fence_callback`.
> + // synchronization: `dma_fence_remove_callback` acquires `fence->lock`,
> + // which ensures that any in-flight `dma_fence_signal` (which calls our
> + // callback while holding the same lock) has completed before we free
> + // the struct.
> + //
> + // Without this, Drop can race with a concurrent signal:
> + // CPU0 (signal, lock held): take() -> signaled(fence_ref) (in progress)
> + // CPU1 (drop): sees is_some()==false -> skips lock -> frees struct
> + // CPU0: accesses fence_ref -> use-after-free
> + //
> + // When the callback has already fired, the signal path detached the
> + // list node via INIT_LIST_HEAD, so dma_fence_remove_callback just sees
> + // an empty node and returns false — the lock acquisition is the only
> + // thing that matters.
> + //
> + // SAFETY: The fence pointer is valid and the cb was initialized by
> + // dma_fence_add_callback during construction.
> + unsafe {
> + bindings::dma_fence_remove_callback(self.fence.as_raw(), self.callback_foreign.get());
> + }
> +
> + // SAFETY: This is literally the drop implementation, so no one has
> + // dropped this so far; so we can do it now.
> + unsafe { ManuallyDrop::<T>::drop(self.project().callback) };
> + }
> +}
> +
> +// SAFETY: FenceCallbackRegistration can be sent between threads.
> +unsafe impl<T: FenceCallback> Send for FenceCallbackRegistration<T> {}
> +
> +// SAFETY: &FenceCallbackRegistration can be shared between threads if &T can.
> +unsafe impl<T: FenceCallback> Sync for FenceCallbackRegistration<T> where T: Sync {}
> +
> +/// The receiving counterpart of a [`DriverFence`].
> +///
> +/// The Rust DMA fence implementation has a dualistic design: [`DriverFence`]s
> +/// are the producer-side, intended to be always owned by only one party. That
> +/// party has the monopoly on signalling the fence.
> +///
> +/// A [`Fence`] is the counterpart for consumers. Thus, [`Fence`]s are always
> +/// refcounted and can shared with an arbitrary number of parties, including
> +/// userspace. A [`Fence`] can only be used for actions such as checking the
> +/// fence's status or for registering callbacks on it.
> +///
> +/// Once the associated [`DriverFence`] signals, all
> +/// [`FenceCallbackRegistration`]s registered on the [`Fence`] will be executed.
> +///
> +/// A [`Fence`] can arbitrarily outlive its [`DriverFence`] and the
> +/// [`FenceContext`]. Signalling a [`DriverFence`] decouples it from its
> +/// [`Fence`]s.
> +#[repr(transparent)]
> +pub struct Fence {
> + /// The actual dma_fence passed to C.
> + inner: Opaque<bindings::dma_fence>,
> +}
> +
> +/// Guard helper for locking within this module.
> +///
> +/// Its only purpose for now is to avoid a number of unsafe lock-unlock cycles.
> +/// It is never used outside of this module.
> +// TODO: This should be made more canonical, probably by basing it on a
> +// SpinLockIrqGuard once available.
> +struct FenceGuard {
> + inner: *mut bindings::dma_fence,
> + flags: usize,
> +}
> +
> +impl Deref for FenceGuard {
> + type Target = *mut bindings::dma_fence;
Why not store and return `&Fence`?
> +
> + fn deref(&self) -> &Self::Target {
> + &self.inner
> + }
> +}
> +
> +impl Drop for FenceGuard {
> + fn drop(&mut self) {
> + // SAFETY: `fence` is valid because `self` is valid. `flag_ptr` is
> + // merely a pointer to an integer, which lives as long as this function.
> + // When a `FenceGuard` exists, the lock has been taken by definition.
> + unsafe { bindings::dma_fence_unlock_irqrestore(self.inner, &raw mut self.flags) };
> + }
> +}
> +
> +// SAFETY: Fences are literally designed to be shared between threads.
> +unsafe impl Send for Fence {}
> +// SAFETY: Fences are literally designed to be shared between threads.
> +unsafe impl Sync for Fence {}
> +
> +impl Fence {
> + /// Check whether the fence was signaled at the moment of the function call.
> + ///
> + /// Note that this can return `true` for a [`Fence`] whose [`DriverFence`]
> + /// has not yet been dropped. The reason is that the fence ops callbacks can
> + /// cause the fence to get signaled by the C backend.
> + pub fn is_signaled(&self) -> bool {
> + // We should not use `dma_fence_is_signaled_locked()` here, because
> + // according to the C backend's recommendations, that function is
> + // problematic and we should avoid calling that function with a lock
> + // held.
> +
> + // SAFETY: Inner `fence` is valid because `self` is valid.
> + let ret = unsafe { bindings::dma_fence_is_signaled(self.as_raw()) };
> +
> + // To be as robust as possible for the future we guarantee that an API
> + // caller can 100% rely on the signalling being completed (i.e., all
> + // fence callbacks ran), so we have to take the lock.
> + //
> + // The reason is that the C dma_fence backend currently does not
> + // carefully synchronize the `dma_fence_is_signaled()` function with the
> + // proper spinlock. This can lead to the function returning `true` while
> + // fence callbacks are still being executed. This can be mitigated by
> + // guarding the entire function with the spinlock.
> + //
> + // The fundamental reason is that the C backend currently does guard
> + // setting of the fence's signaled-bit with the fence's spinlock, but
> + // reading is done locklessly.
> + //
> + // See commit c8a5d5ea3ba6a.
> +
Extra newline here.
> + let _ = self.lock();
> +
> + ret
> + }
> +
#[inline] here and many more below.
> + fn lock(&self) -> FenceGuard {
> + let mut guard = FenceGuard {
> + inner: self.as_raw(),
> + flags: 0,
> + };
> +
> + // SAFETY: `fence` is valid because `self` is valid. `flag_ptr` is
> + // merely a pointer to an integer, whose lifetime is tied to the guard
> + // object.
> + unsafe { bindings::dma_fence_lock_irqsave(guard.inner, &raw mut guard.flags) };
> +
> + guard
> + }
> +
> + /// Get the fence's sequence number.
> + pub fn seqno(&self) -> u64 {
> + // SAFETY: Valid because `self` is valid.
> + unsafe { (*self.as_raw()).seqno }
> + }
> +
> + fn as_raw(&self) -> *mut bindings::dma_fence {
> + self.inner.get()
> + }
> +
> + /// Create a [`Fence`] from a raw C [`bindings::dma_fence`].
> + ///
> + /// # Safety
> + ///
> + /// `ptr` must point to an initialized fence that is embedded into a [`Fence`].
> + pub unsafe fn from_raw<'a>(ptr: *mut bindings::dma_fence) -> &'a Self {
> + // SAFETY: Safe as per the function's overall safety requirements.
> + unsafe { &*ptr.cast() }
> + }
> +}
> +
> +// SAFETY: These implement the C backends refcounting methods which are proven
> +// to work correctly.
> +unsafe impl AlwaysRefCounted for Fence {
> + fn inc_ref(&self) {
> + // SAFETY: `self.as_raw()` is a pointer to a valid `struct dma_fence`.
> + unsafe { bindings::dma_fence_get(self.as_raw()) }
> + }
> +
> + /// # Safety
> + ///
> + /// `ptr`must be a valid pointer to a [`DriverFence`].
> + unsafe fn dec_ref(ptr: NonNull<Self>) {
> + // SAFETY: `ptr` is never a NULL pointer; and when `dec_ref()` is called
> + // the fence is by definition still valid.
> + let fence = unsafe { (*ptr.as_ptr()).inner.get() };
> +
> + // SAFETY: `fence` was created validly above. When `dec_ref()` is called,
> + // there is by definition still a reference alive that can be put.
> + unsafe { bindings::dma_fence_put(fence) }
> + }
> +}
> +
> +// Necessary to guarantee that `inner` always comes first and can be freed by C.
> +// Also useful for using casts instead of container_of().
> +#[repr(C)]
> +#[pin_data]
> +struct DriverFenceData<'a, T: Send + Sync + FenceContextOps> {
> + #[pin]
> + /// The inner fence.
> + // Must always be the first member so that unsafe casting works; but also
> + // necessary so that the C backend can free the allocation (coming from our
> + // Rust code) with kfree_rcu().
> + inner: Fence,
> + /// Callback head for dropping this in a deferred manner through RCU.
> + rcu_head: bindings::callback_head,
> + /// Reference to access the FenceContext. Useful for obtaining name parameters.
> + fctx: &'a FenceContext<T>,
> + /// The API user's data. It is essential that the data only performs
> + /// operations legal in atomic context in its [`Drop`] implementation.
> + #[pin]
> + data: T::FenceDataType,
> +}
> +
> +/// A synchronization primitive mainly for GPU drivers.
> +///
> +/// The Rust DMA fence implementation has a dualistic design: [`DriverFence`]s
> +/// are the producer-side, intended to be always owned by only one party. That
> +/// party has the monopoly on signalling the fence.
> +///
> +/// A [`Fence`] is the counterpart for consumers. Thus, [`Fence`]s are always
> +/// refcounted and can shared with an arbitrary number of parties, including
> +/// userspace. A [`Fence`] can only be used for actions such as checking the
> +/// fence's status or for registering callbacks on it.
> +///
> +/// Once the associated [`DriverFence`] signals, all
> +/// [`FenceCallbackRegistration`]s registered on a [`Fence`] will be executed.
> +///
> +/// A [`Fence`] can arbitrarily outlive its [`DriverFence`] and the
> +/// [`FenceContext`]. Signalling a [`DriverFence`] decouples it from its
> +/// [`Fence`]s.
> +///
> +/// It is crucial that a [`DriverFence`] always correctly represents the state
> +/// of the associated job on the hardware. Especially, it is strictly necessary
> +/// that the owner ensures that all [`DriverFence`]s eventually get signaled.
> +/// As a last resort, a [`DriverFence`] will signal itself if it drops
> +/// unsignaled and print a warning.
> +///
> +/// This design intends to implement the [`bindings::dma_fence_ops`] in such a
> +/// way that the driver-data necessary to implement the callback's functionality
> +/// resides in the [`FenceContext`]. Thus, a [`DriverFence`] contains a
> +/// reference to the context, which can be accessed in the callbacks. The
> +/// implementation, therefore, ensures that a [`DriverFence`] cannot outlive its
> +/// [`FenceContext`]. Unfortunately, this can be circumvented under certain
> +/// circumstances in Rust (e.g., usage of [`core::mem::forget`]).
> +///
> +/// In the unlikely case of such violations, error warnings are printed.
> +///
> +/// # Examples
> +///
> +/// ```
> +/// use kernel::dma_buf::{
> +/// DriverFence,
> +/// FenceContext,
> +/// FenceContextOps,
> +/// FenceCallback,
> +/// FenceCallbackRegistration, //
> +/// };
> +/// use kernel::str::CString;
> +/// use kernel::sync::aref::ARef;
> +/// use core::fmt::Display;
> +///
> +/// struct CallbackData { }
> +///
> +/// impl FenceCallback for CallbackData {
> +/// fn called(&mut self) {
> +/// pr_info!("DmaFence callback executed.\n");
> +/// }
> +/// }
> +///
> +/// #[pin_data]
> +/// struct FenceContextData {}
> +///
> +/// impl FenceContextData {
> +/// fn new() -> impl PinInit<Self> {
> +/// pin_init!(Self {})
> +/// }
> +/// }
> +///
> +/// impl FenceContextOps for FenceContextData {
> +/// type FenceDataType = FenceData;
> +/// }
> +///
> +/// let fctx_data = FenceContextData::new();
> +///
> +/// let driver_name = CString::try_from_fmt(fmt!("dummy_driver"))?;
> +/// let timeline_name = CString::try_from_fmt(fmt!("dummy_timeline"))?;
> +///
> +/// let mut fctx = KBox::pin_init(
> +/// FenceContext::new(0, driver_name, timeline_name, fctx_data), GFP_KERNEL)?;
> +///
> +/// struct FenceData {
> +/// data: CString,
> +/// }
> +///
> +/// let data = CString::try_from_fmt(fmt!("dummy_data"))?;
> +/// let fence_data = FenceData { data };
> +///
> +/// let fence_alloc = fctx.new_fence_allocation(fence_data)?;
> +/// let mut fence = fence_alloc.new_fence();
> +///
> +/// let cb_data = CallbackData { };
> +/// let waiting_fence = ARef::from(fence.as_fence());
> +/// let cb_reg = FenceCallbackRegistration::new(&waiting_fence, cb_data);
> +/// let cb_reg = KBox::pin_init(cb_reg, GFP_KERNEL)?;
> +///
> +/// // TODO signalling guards
> +/// fence.signal(Ok(()));
> +/// assert_eq!(waiting_fence.is_signaled(), true);
> +///
> +/// Ok::<(), Error>(())
> +/// ```
> +pub struct DriverFence<'a, T: Send + Sync + FenceContextOps> {
> + /// The actual content of the fence. Lives in a [`NonNull`] so that its
> + /// memory can be managed independently. Valid until both the [`DriverFence`]
> + /// and all associated [`Fence`]s have disappeared.
> + data: NonNull<DriverFenceData<'a, T>>,
> +}
> +
> +/// A pre-prepared DMA fence, carrying the user's data and the memory it and the
> +/// fence reside in. Only useful for creating a [`DriverFence`]. Splitting
> +/// allocation and full initialization is necessary because fences cannot be
> +/// allocated dynamically in some circumstances (deadlock).
> +pub struct DriverFenceAllocation<'a, T: Send + Sync + FenceContextOps> {
> + /// The memory for the actual content of the fence.
> + /// Handed over to a [`DriverFence`], or deallocated once the
> + /// [`DriverFenceAllocation`] drops.
> + data: KBox<DriverFenceData<'a, T>>,
> + /// Pointer for the ops for the associated [`FenceContext`]
> + ops: *const bindings::dma_fence_ops,
> +}
> +
> +impl<'a, T: Send + Sync + FenceContextOps> DriverFenceAllocation<'a, T> {
> + /// Create a new fence, consuming `data`.
There's no `data`.
> + ///
> + /// This increments the sequence number in the associated [`FenceContext`].
> + pub fn new_fence(self) -> DriverFence<'a, T> {
> + // We feed the C dma_fence backend a NULL for the spinlock so that it
> + // uses per-fence locks automatically.
> + let null_ptr: *mut bindings::spinlock = ptr::null_mut();
> + let seqno = self.data.fctx.next_seqno();
> + let fence_ptr = self.as_raw();
> + // SAFETY: `fence_ptr` has been created directly above. It will live
> + // at least as long as `Self`. The same applies to `&Self::OPS`.
> + unsafe {
> + bindings::dma_fence_init(fence_ptr, self.ops, null_ptr, self.data.fctx.nr, seqno)
> + };
> +
> + self.data.fctx.nr_of_unsignaled_fences.fetch_add(1, Relaxed);
> +
> + // A `DriverFenceAllocation`'s purpose is to carry allocated memory, so that
> + // `DriverFence`s can always be created without allocating. In this
> + // method, ownership over that memory is transferred to the new
> + // `DriverFence` and managed through refcounting. The C dma_fence
> + // backend will ultimately free the memory once the refcount reaches 0.
> + let ptr = KBox::into_raw(self.data);
> + // SAFETY: `ptr` was just created validly directly above.
> + let ptr = unsafe { NonNull::new_unchecked(ptr) };
> +
> + DriverFence { data: ptr }
> + }
> +
> + fn as_raw(&self) -> *mut bindings::dma_fence {
> + self.data.inner.inner.get()
> + }
> +}
> +
> +impl<'a, T: Send + Sync + FenceContextOps> DriverFence<'a, T> {
> + fn as_raw(&self) -> *mut bindings::dma_fence {
> + // SAFETY: Valid because `self` is valid.
> + let fence_data = unsafe { &*self.data.as_ptr() };
> +
> + fence_data.inner.inner.get()
> + }
> +
> + /// Create a [`DriverFence`] from a raw pointer to a [`bindings::dma_fence`].
> + ///
> + /// # Safety
> + ///
> + /// `ptr` must be a valid pointer to a `dma_fence` that was obtained through
> + /// a [`DriverFence`] with matching generic data for both fence and associated
> + /// [`FenceContext`].
> + unsafe fn from_raw(ptr: *mut bindings::dma_fence) -> Self {
> + let opaque_fence = Opaque::cast_from(ptr);
> +
> + // SAFETY: Safe due to the function's overall safety requirements.
> + let fence_ptr = unsafe { container_of!(opaque_fence, Fence, inner) };
> +
> + // DriverFenceData is repr(C) and a Fence is its first member.
> + let fence_data_ptr = fence_ptr as *mut DriverFenceData<'a, T>;
> +
> + // SAFETY: `fence_data_ptr` was created validly above.
> + let data = unsafe { NonNull::new_unchecked(fence_data_ptr) };
> +
> + Self { data }
> + }
> +
> + /// Return the underlying [`Fence`].
> + pub fn as_fence(&self) -> &Fence {
> + // SAFETY: `self` is by definition still valid, and it cannot drop until
> + // this new reference is gone.
> + unsafe { Fence::from_raw(self.as_raw()) }
> + }
> +
> + /// Signal the fence. This will invoke all registered callbacks.
> + pub fn signal(self, res: Result) {
> + let fence = self.as_fence().lock();
> +
> + // SAFETY: `fence` is valid because `self` is valid. The lock must be
> + // held, which we acquired directly above.
> + if !unsafe { bindings::dma_fence_test_signaled_flag(*fence.deref()) } {
These `*fence.deref()` are quite weird as consequence of `FenceGuard` design.
If `FenceGuard` just derefs to `&Fence` then this can be `fence.as_raw()`.
> + if let Err(err) = res {
> + // SAFETY: `fence` is valid because `self` is valid. The fence
> + // must not have been signaled yet, which we check directly above.
> + unsafe { bindings::dma_fence_set_error(*fence.deref(), err.to_errno()) };
> + }
> + // SAFETY: `fence` is valid because `self` is valid. The lock must
> + // be held, which we acquired above.
> + unsafe { bindings::dma_fence_signal_locked(*fence.deref()) };
> + }
> +
> + // SAFETY: `self.data` is valid because `self` is valid.
> + let fctx = unsafe { self.data.as_ref().fctx };
> + let _ = fctx.nr_of_unsignaled_fences.fetch_sub(1, Relaxed);
Drop impl of `self` here will neededlessly take lock again before checking it's
signaled already and unlock.
> + }
> +}
> +
> +// SAFETY: Fences are literally designed to be shared between threads.
> +unsafe impl<'a, T: Send + Sync + FenceContextOps> Send for DriverFence<'a, T> {}
> +// SAFETY: Fences are literally designed to be shared between threads.
> +unsafe impl<'a, T: Send + Sync + FenceContextOps> Sync for DriverFence<'a, T> {}
> +
> +impl<'a, T: Send + Sync + FenceContextOps> Deref for DriverFence<'a, T> {
> + type Target = T::FenceDataType;
> +
> + fn deref(&self) -> &Self::Target {
> + // SAFETY: Thanks to refcounting, `data` is always valid as long as `self` is.
> + let data = unsafe { &*self.data.as_ptr() };
> +
> + &data.data
> + }
> +}
> +
> +/// A borrow wrapper for [`DriverFence`]. Implements [`Deref`].
> +pub struct DriverFenceBorrow<'a, T: Send + Sync + FenceContextOps> {
> + driver_fence: ManuallyDrop<DriverFence<'a, T>>,
> + _lifetime: PhantomData<&'a T>,
> +}
> +
> +impl<'a, T: Send + Sync + FenceContextOps> Deref for DriverFenceBorrow<'a, T> {
> + type Target = DriverFence<'a, T>;
> +
> + fn deref(&self) -> &Self::Target {
> + self.driver_fence.deref()
> + }
> +}
> +
> +// SAFETY: The Rust dma_fence abstractions are already designed around the inner
> +// C `dma_fence`, which can serve safely as the identification point when being
> +// owned by C. Moreover, safety is ensured by not dropping `DriverFence` and by
> +// only allowing operations without side effects on the Borrowed type.
> +unsafe impl<T: Send + Sync + FenceContextOps + 'static> ForeignOwnable for DriverFence<'_, T> {
The `'static` shouldn't be needed here.
> + type Borrowed<'a>
> + = DriverFenceBorrow<'a, T>
> + where
> + Self: 'a;
> + type BorrowedMut<'a>
> + = DriverFenceBorrow<'a, T>
> + where
> + Self: 'a;
> +
> + const FOREIGN_ALIGN: usize = core::mem::align_of::<bindings::dma_fence>();
> +
> + fn into_foreign(self) -> *mut c_void {
> + let fence = self;
> +
> + let ptr = fence.as_raw();
> +
> + // DriverFence must not drop.
> + let _ = ManuallyDrop::new(fence);
> +
> + ptr.cast()
> + }
> +
> + unsafe fn from_foreign(ptr: *mut c_void) -> Self {
> + // SAFETY: Safe because the trait implementation only invokes this with
> + // a valid `ptr`, associated to a `DriverFence` with matching generic data.
> + unsafe { Self::from_raw(ptr.cast()) }
> + }
> +
> + unsafe fn borrow<'a>(ptr: *mut c_void) -> Self::Borrowed<'a>
> + where
> + Self: 'a,
> + {
> + // SAFETY: The trait implementation ensures that `ptr` always resides
> + // within a [`Fence`] within a [`DriverFenceData`].
> + let driver_fence = unsafe { Self::from_raw(ptr.cast()) };
> +
> + let driver_fence = ManuallyDrop::new(driver_fence);
> +
> + DriverFenceBorrow {
> + driver_fence,
> + _lifetime: PhantomData,
> + }
> + }
> +
> + unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> Self::BorrowedMut<'a>
> + // FIXME: The bound below and the one above in `borrow` should actually be
> + // unnecessary since the compiler should be able to completely derive all
> + // necessary information automatically. There is currently a compiler bug
> + // preventing that, though:
> + //
> + // https://github.com/rust-lang/rust/issues/155430.
> + //
> + // (Help to) fix the compiler bug and remove the bounds afterwards.
> + where
> + Self: 'a,
> + {
> + // SAFETY: The trait implementation ensures that `ptr` always resides
> + // within a [`Fence`] within a [`DriverFenceData`].
> + let driver_fence = unsafe { Self::from_raw(ptr.cast()) };
> +
> + let driver_fence = ManuallyDrop::new(driver_fence);
> +
> + DriverFenceBorrow {
> + driver_fence,
> + _lifetime: PhantomData,
> + }
> + }
> +}
> +
> +impl<'a, T: Send + Sync + FenceContextOps> Drop for DriverFence<'a, T> {
> + fn drop(&mut self) {
> + let guard = self.as_fence().lock();
> +
> + // Use dma_fence_test_signaled_flag() instead of
> + // dma_fence_is_signaled_locked() because the C backend wants to get rid
> + // of the latter.
> +
> + // SAFETY: `guard` is valid until the `call_rcu()` below.
> + let signaled: bool = unsafe { bindings::dma_fence_test_signaled_flag(*guard.deref()) };
> + if !signaled {
> + pr_err!("DriverFence drops unsignaled. Danger of memory corruption!\n");
> + // SAFETY: `guard` is valid until the `call_rcu()` below. The fence
> + // must not have been signaled yet, which we check directly above.
> + unsafe { bindings::dma_fence_set_error(*guard.deref(), ECANCELED.to_errno()) };
> + // SAFETY: `guard` is valid until the `call_rcu()` below. The lock
> + // must be held, which we acquired above.
> + unsafe { bindings::dma_fence_signal_locked(*guard.deref()) };
> +
> + // SAFETY: `self.data` is valid because `self` is valid.
> + let fctx = unsafe { self.data.as_ref().fctx };
> + let _ = fctx.nr_of_unsignaled_fences.fetch_sub(1, Relaxed);
> + }
> + drop(guard);
> +
> + // SAFETY: Valid because `self` is valid.
> + let rcu_head_ptr = unsafe { &raw mut (*self.data.as_ptr()).rcu_head };
> +
> + // `DriverFenceData` but could be accessed through some dma_fence
> + // callbacks right now. Access is being revoked in principle above by
> + // signalling the fence, but since the C backend does not guarantee
> + // perfect full synchronization, we have to wait for one grace period to
> + // ensure that all accessors of `DriverFenceData` (through the
> + // dma_fence_ops accessible through a `Fence`) are gone.
> +
> + // SAFETY: `call_rcu()` is always safe to be called. `rcu_head_ptr` was
> + // created validly above. The module must perform a `synchronize_rcu()`
> + // or `rcu_barrier()` call to guard against module unload.
> + unsafe { bindings::call_rcu(rcu_head_ptr, Some(drop_driver_fence_data::<T>)) };
I thought at some point it was mentioned that we want a fast path
if !mem::needs_drop::<...>() {
}
?
> + }
> +}
> +
> +// TODO:
> +// The entire call_rcu() mechanism in the drop above and the code below would be
> +// unnecessary if C's dma_fence_signal() could be reworked in a way that after it
> +// ran, the caller knows that no fence_ops callbacks can be running anymore.
> +// In other words, if the dma_fence backend would use its spinlock for full
> +// synchronization.
> +//
> +// Then we could move the drop_in_place() and dma_fence_put() upwards into the
> +// drop() implementation and call it a day.
> +
> +/// Finally really drop this `DriverFence<T>`
> +///
> +/// # Safety
> +///
> +/// `head` references the `rcu_head` field of an `DriverFenceData<T>`. All
> +/// accessors to that `DriverFenceData<T>` must be gone by now. This must be
> +/// ensured by signalling the associated `DriverFence<T>` and then waiting
> +/// for a grace period until calling this function here.
> +unsafe extern "C" fn drop_driver_fence_data<T: Send + Sync + FenceContextOps>(
> + head: *mut bindings::callback_head,
> +) {
> + // SAFETY: Caller provides a pointer to the `rcu_head` field of a `DriverFenceData<C>`.
> + let fence_data = unsafe { container_of!(head, DriverFenceData<'_, T>, rcu_head) };
> +
> + // SAFETY: `fence_data` was created validly above. All the fence's data will
> + // only drop below, but the raw pointer to the raw C `dma_fence` remains
> + // valid because the reference count is only decremented at the end of the
> + // function.
> + let fence = unsafe { (*fence_data).inner.inner.get() };
> +
> + // SAFETY: `fence_data` was created validly above. A grace period has passed.
> + // All callbacks which might have had access to the `fctx` are gone now.
> + unsafe { drop_in_place(&raw mut (*fence_data).fctx) };
fctx is just a reference, so this is a no-op.
Best,
Gary
> +
> + // SAFETY: `fence_data` was created validly above. The user has already
> + // dropped the only conventional accessor to the user data, the `DriverFence`,
> + // one grace period ago. All accessors are gone now.
> + unsafe { drop_in_place(&raw mut (*fence_data).data) };
> +
> + // The inner `Fence` explicitly does not get dropped because there may be
> + // many more users / consumers, each holding their own reference.
> +
> + // SAFETY: Once a `DriverFence` is initialized, the inner `fence` is
> + // valid and initialized. It is valid until the refcount drops
> + // to 0, which can earliest happen once we drop the `DriverFence`'s reference
> + // here.
> + unsafe { bindings::dma_fence_put(fence) };
> +
> + // The actual memory the data associated with a `DriverFence` lives in
> + // gets freed by the C dma_fence backend once the fence's refcount reaches 0.
> +}
> diff --git a/rust/kernel/dma_buf/mod.rs b/rust/kernel/dma_buf/mod.rs
> new file mode 100644
> index 000000000000..4764a828642e
> --- /dev/null
> +++ b/rust/kernel/dma_buf/mod.rs
> @@ -0,0 +1,14 @@
> +// SPDX-License-Identifier: GPL-2.0 OR MIT
> +
> +//! DMA-buf subsystem abstractions.
> +
> +pub mod dma_fence;
> +
> +pub use self::dma_fence::{
> + DriverFence,
> + Fence,
> + FenceCallback,
> + FenceCallbackRegistration,
> + FenceContext,
> + FenceContextOps, //
> +};
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index 68f4d9a3425d..6221ebfe71df 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -67,6 +67,7 @@
> pub mod device_id;
> pub mod devres;
> pub mod dma;
> +pub mod dma_buf;
> pub mod driver;
> #[cfg(CONFIG_DRM = "y")]
> pub mod drm;
The gameplay in granny 1 https://granny-1.io focuses on stealth and puzzle-solving rather than direct combat, making awareness and patience the most important skills. Players must move quietly through corridors, avoid making noise, and pay attention to every sound since granny can hear even the smallest disturbance. The house is filled with locked doors, secret areas, and interactive objects that create a constant sense of mystery and discovery. Each item you collect, such as keys, tools, or special components, plays a role in helping you progress toward escape.
One of the main reasons why Sprunki Game https://sprunkigames.io has become so popular is its accessibility. Players do not need any musical knowledge or experience to enjoy the game. The drag-and-drop gameplay is easy to understand, allowing anyone to start creating music within minutes. At the same time, the large number of sound combinations provides enough depth to keep players engaged for hours.
Steal Brainrot has quickly become a popular online game that attracts players through a mix of creativity, strategy, humor, and unexpected challenges. The game delivers a unique experience where players collect unusual characters, compete with others, and build their own progress through smart decisions. With a simple concept but highly addictive gameplay, Steal Brainrot creates an entertaining environment for casual players and dedicated fans. https://stealbrainrotgame.io/
The game stands out because of its combination of funny elements and competitive mechanics. Players must think carefully about how to manage resources, protect valuable items, and discover new opportunities. Every session brings different situations, making the gameplay feel fresh and exciting.
What Is Steal Brainrot?
Steal Brainrot is an online multiplayer game focused on collecting and stealing valuable Brainrot characters. The main goal involves gathering rare items, improving personal collections, and competing against other players. The game uses a humorous style with creative designs that make each character memorable.
Unlike traditional games that focus only on fighting or exploration, Steal Brainrot creates entertainment through interaction between players. The competition comes from trying to obtain better Brainrot characters while defending personal progress from opponents.
The simple gameplay design allows beginners to understand the basic mechanics quickly. However, reaching higher levels requires planning, timing, and knowledge about available opportunities inside the game world.
The Main Concept Behind Steal Brainrot
The core idea of Steal Brainrot revolves around collecting Brainrot characters and increasing their value. Players start with basic resources before expanding their collection through different actions. The excitement comes from finding rare characters and deciding the best way to use them.
Every Brainrot character has different levels of rarity and importance. Some characters are easier to obtain, while others require more effort and strategic thinking. This creates motivation for players who enjoy collecting and completing goals.
The stealing mechanic adds another layer of challenge. Players must stay alert because other competitors can attempt to take valuable Brainrot characters. This constant risk makes every decision more meaningful.
Why Steal Brainrot Becomes Popular
The popularity of Steal Brainrot comes from several important factors. First, the game provides a funny and entertaining atmosphere that appeals to a wide audience. The unusual character designs and creative ideas help the game create a recognizable identity.
Another reason for its success is the competitive multiplayer system. Players are not only focused on personal progress but also on interactions with other users. This creates exciting moments that encourage people to return and continue playing.
The game also benefits from its easy accessibility. New players can quickly understand the basic rules without needing complicated tutorials. At the same time, experienced players can develop advanced strategies to improve performance.
Gameplay Features In Steal Brainrot
Steal Brainrot includes many features that make the experience more engaging. The combination of collection systems, competition, and progression creates a gameplay loop that keeps players interested.
Collecting Valuable Brainrot Characters
Collection is one of the most important parts of Steal Brainrot. Players spend time searching for different Brainrot characters and building stronger collections. Finding rare characters provides a sense of achievement and encourages continued exploration.
The collecting system creates long-term goals because players always have new targets to discover. Whether searching for uncommon characters or improving an existing collection, players always have something to work toward.
Strategic Stealing Mechanics
The stealing system gives Steal Brainrot a unique competitive element. Players must decide when to attack and when to focus on protecting their own progress. A good strategy requires patience, observation, and smart timing.
Successful players understand that rushing into every opportunity may create unnecessary risks. Careful planning helps increase the chance of gaining valuable Brainrot characters while avoiding major losses.
Multiplayer Competition And Social Interaction
Steal Brainrot becomes more exciting because of multiplayer interaction. Every player creates a different experience through personal strategies and decisions. Encounters with other players can change the direction of a game session.
The social aspect also helps build a stronger community. Players can share strategies, discuss rare characters, and compete to achieve better results. This connection between players contributes to the long-lasting appeal of the game.
Tips To Improve Performance In Steal Brainrot
Although Steal Brainrot is easy to start, improving skills requires experience and understanding. Players who want better results should focus on smart resource management and careful decisions.
Focus On Building A Strong Collection
A strong collection provides more opportunities for success. Players should prioritize finding valuable Brainrot characters instead of making random decisions. Understanding which characters provide higher value can create a significant advantage.
Patience is also important because rare items may require more time and effort. Consistent progress often leads to better results than quick but risky actions.
Protect Important Resources
Defense plays an important role in Steal Brainrot. Players should avoid exposing valuable characters unnecessarily and should always consider possible risks.
Good protection strategies help maintain progress and reduce losses caused by other competitors. Balancing offense and defense creates a more effective gameplay approach.
Learn From Other Players
Observing experienced players can help improve skills faster. Many advanced strategies come from understanding how other users manage collections and handle competition.
Learning from different play styles allows players to develop personal strategies that match their goals. The more players understand the game mechanics, the better decisions they can make.
The Future Of Steal Brainrot
Steal Brainrot has strong potential to continue growing because of its creative gameplay and active player interest. Games with unique concepts often attract attention when they provide memorable experiences.
Future updates could introduce new Brainrot characters, additional challenges, and improved features that increase player engagement. Expanding content can help maintain excitement and encourage more people to join the community.
The combination of humor, competition, and collection makes Steal Brainrot different from many other online games. Its simple design creates accessibility, while its strategic elements provide depth for long-term players.
Conclusion
Steal Brainrot offers a fun and competitive gaming experience through creative characters, collecting mechanics, and exciting multiplayer interactions. The game attracts players who enjoy discovering new items, creating strategies, and competing with others.
With an entertaining concept and endless opportunities for improvement, Steal Brainrot continues to capture attention from gaming communities. Whether playing casually or aiming for competitive success, players can find enjoyable moments throughout the journey.
On 8/5/26 12:59, Pavel Begunkov wrote:
> On 8/5/26 09:27, Christian König wrote:
>>> +
>>> +Â Â Â dma_resv_lock(dmabuf->resv, NULL);
>>> +Â Â Â ctx->dev_ops->unmap(ctx, map);
>>> +Â Â Â dma_resv_unlock(dmabuf->resv);
>>> +
>>> +Â Â Â dma_fence_put(&fence->base);
>>
>> You should probably set map->fence to NULL after that.
>
> The map is freed two lines below, but I can add it as
> a defensive measure.
In that case it's ok, I've just haven't seen the kfree(map) below.
> ...
>>> +Â Â Â ret = dma_resv_reserve_fences(dmabuf->resv, 1);
>>> +Â Â Â if (WARN_ON_ONCE(ret)) {
>>> +Â Â Â Â Â Â Â struct dma_fence *fence = &map->fence->base;
>>> +
>>> +Â Â Â Â Â Â Â dma_fence_get(fence);
>>> +Â Â Â Â Â Â Â percpu_ref_kill(&map->refs);
>>> +Â Â Â Â Â Â Â dma_fence_wait(fence, false);
>>> +Â Â Â Â Â Â Â dma_fence_put(fence);
>>> +Â Â Â Â Â Â Â return;
>>> +Â Â Â }
>>> +
>>> +Â Â Â dma_resv_add_fence(dmabuf->resv, &map->fence->base,
>>> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â DMA_RESV_USAGE_KERNEL);
>>
>> That sequence is clearly incorrect!
>>
>> The fence must be created after dma_resv_reserve_fences(), otherwise you definately have an illegal memory operation here.
>
> I'm not sure what you mean, can you elaborate? I only cared about
> pre-allocating it to avoid allocations here. We add / signal the fence
> only once, no reuse. The map is going to be killed here, and if we
> create a new map, it'll have its own fence.
>
> I can move the dma_fence_init() call here if that makes a difference?
Yeah that is a good start, but you might need a bit more.
Here is a summary of the usual procedure you need to follow when implementing a dma_fence backend:
1. Allocate your operation object, in this case here it's your mapping I think.
2. Prepare your operation, including all memory allocations.
3. Call dma_resv_reserve_fences() to reserve a fence slot.
4. Allocate and init your dma_fence object.
After this step no memory allocation is allowed any more until your dma_fence object signals.
The only exception is optional logging or crash dumping using GFP_NOWAIT (can fail trivially!) or minimal allocations using GFP_ATOMIC if you absolutely have to.
5. dma_resv_add_fence() to publish the fence.
6. dma_resv_unlock().
Having a dma_fence is certainly nice to have, but the tricky part is that memory allocations using GFP_KERNEL (or GFP_IO, GFP_FS etc...) can cycle back and wait for your dma_fence to signal which essentially can cause a deadlock very deeply inside memory management.
Since those deadlocks happen only on memory contention situations they are usually just hard to reproduce but still totally break your neck if you manage to mess this up. So that needs to be super carefully implemented.
Regards,
Christian.