Skip to main content

DriverFence

Struct DriverFence 

Source
pub struct DriverFence<'a, T: Send + Sync + FenceContextOps> { /* private fields */ }
Expand description

A synchronization primitive mainly for GPU drivers.

The Rust DMA fence implementation has a dualistic design: DriverFences are the producer-side, intended to be always owned by only one party. That party has the monopoly on signaling the fence.

A Fence is the counterpart for consumers. Thus, Fences are always refcounted and can be 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 FenceCallbackRegistrations registered on a Fence will be executed.

A Fence can arbitrarily outlive its DriverFence and the FenceContext. Signaling a DriverFence decouples it from its Fences.

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 DriverFences 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, a panic is thrown.

§Examples

use kernel::{
    dma_buf::{
        DriverFence,
        FenceContext,
        FenceContextOps,
        FenceCallback,
        FenceCallbackRegistration,
    },
    str::CString,
    sync::aref::ARef, //
};
use core::fmt::Display;

struct CallbackData { }

impl FenceCallback for CallbackData {
    fn on_signal(&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 mut fctx = KBox::pin_init(
    FenceContext::new(0, c"dummy_driver", c"dummy_timeline", fctx_data),
    GFP_KERNEL
)?;

struct FenceData {
    data: CString,
}

let fence_data = FenceData { data: c"dummy_data".try_into()? };

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
assert_eq!(waiting_fence.is_signaled(), false);
fence.signal(Ok(()));
assert_eq!(waiting_fence.is_signaled(), true);

Ok::<(), Error>(())

Implementations§

Source§

impl<'a, T: Send + Sync + FenceContextOps> DriverFence<'a, T>

Source

pub fn as_fence(&self) -> &Fence

Return the underlying Fence.

Source

pub fn signal(self, res: Result)

Signal the fence. This will invoke all registered callbacks.

Trait Implementations§

Source§

impl<'a, T: Send + Sync + FenceContextOps> Deref for DriverFence<'a, T>

Source§

type Target = <T as FenceContextOps>::FenceDataType

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<'a, T: Send + Sync + FenceContextOps> Drop for DriverFence<'a, T>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl<T: Send + Sync + FenceContextOps> ForeignOwnable for DriverFence<'_, T>

Source§

const FOREIGN_ALIGN: usize

The alignment of pointers returned by into_foreign.
Source§

type Borrowed<'a> = DriverFenceBorrow<'a, T> where Self: 'a

Type used to immutably borrow a value that is currently foreign-owned.
Source§

type BorrowedMut<'a> = DriverFenceBorrow<'a, T> where Self: 'a

Type used to mutably borrow a value that is currently foreign-owned.
Source§

fn into_foreign(self) -> *mut c_void

Converts a Rust-owned object to a foreign-owned one. Read more
Source§

unsafe fn from_foreign(ptr: *mut c_void) -> Self

Converts a foreign-owned object back to a Rust-owned one. Read more
Source§

unsafe fn borrow<'a>(ptr: *mut c_void) -> Self::Borrowed<'a>
where Self: 'a,

Borrows a foreign-owned object immutably. Read more
Source§

unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> Self::BorrowedMut<'a>
where Self: 'a,

Borrows a foreign-owned object mutably. Read more
Source§

unsafe fn try_from_foreign(ptr: *mut c_void) -> Option<Self>

Tries to convert a foreign-owned object back to a Rust-owned one. Read more
Source§

impl<'a, T: Send + Sync + FenceContextOps> Send for DriverFence<'a, T>

Source§

impl<'a, T: Send + Sync + FenceContextOps> Sync for DriverFence<'a, T>

Auto Trait Implementations§

§

impl<'a, T> !RefUnwindSafe for DriverFence<'a, T>

§

impl<'a, T> !UnwindSafe for DriverFence<'a, T>

§

impl<'a, T> Freeze for DriverFence<'a, T>
where NonNull<DriverFenceData<'a, T>>: Freeze,

§

impl<'a, T> Unpin for DriverFence<'a, T>
where NonNull<DriverFenceData<'a, T>>: Unpin,

§

impl<'a, T> UnsafeUnpin for DriverFence<'a, T>
where NonNull<DriverFenceData<'a, T>>: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Init<T> for T

Source§

fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
where F: FnOnce(&mut T) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<S, T> IntoSafeCast<T> for S
where T: FromSafeCast<S>,

Source§

fn into_safe_cast(self) -> T

Convert self into a T. This operation is guaranteed to be lossless.
Source§

impl<S, T> IntoSafeCastArch<T> for S
where T: FromSafeCastArch<S>,

Source§

fn into_safe_cast_arch(self) -> T

Convert self into a T. This operation is guaranteed to be lossless.
Source§

impl<T> KnownSize for T

Source§

const MIN_SIZE: usize = const MIN_SIZE: usize = size_of::<T>();

Minimum size of this type known at compile-time.
Source§

const MIN_ALIGN: Alignment = const MIN_ALIGN: Alignment = Alignment::of::<T>();

Minimum alignment of this type known at compile-time.
Source§

fn size(_: *const T) -> usize

Get the size of an object of this type in bytes, with the metadata of the given pointer.
Source§

impl<T> PinInit<T> for T

Source§

unsafe fn __init(self, slot: *mut T) -> Result<(), !>

Initializes slot. Read more
Source§

fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
where F: FnOnce(Pin<&mut T>) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. Read more
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T, U, const N: u32> TryIntoBounded<T, N> for U
where T: Integer, U: TryInto<T>,

Source§

fn try_into_bounded(self) -> Option<Bounded<T, N>>

Attempts to convert self into a Bounded using N bits. Read more