Module: Mesa Branch: main Commit: e461944060140f75b61af0aea1e0e1cf77acc01e URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=e461944060140f75b61af0aea1e0e1cf77acc01e
Author: LingMan <[email protected]> Date: Wed Oct 11 21:26:05 2023 +0200 rusticl: add structs to hold the C callbacks Keeps function pointers and their provided user data together. Since these callbacks are guaranteed to be thread-safe by the OpenCL spec, they are marked Send and Sync. Reviewed-by: Karol Herbst <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25669> --- src/gallium/frontends/rusticl/api/types.rs | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/gallium/frontends/rusticl/api/types.rs b/src/gallium/frontends/rusticl/api/types.rs index b4a4c1ac7aa..b5486a7e522 100644 --- a/src/gallium/frontends/rusticl/api/types.rs +++ b/src/gallium/frontends/rusticl/api/types.rs @@ -1,6 +1,9 @@ +use crate::api::icd::CLResult; + use rusticl_opencl_gen::*; use std::borrow::Borrow; +use std::ffi::c_void; use std::iter::Product; #[macro_export] @@ -22,6 +25,53 @@ macro_rules! cl_callback { pub type $fn_alias = unsafe extern "C" fn( $($p: $ty,)* ); + + // INVARIANT: + // All safety requirements on `func` and `data` documented on `$cb::new` are invariants. + pub struct $cb { + pub func: $fn_alias, + pub data: *mut c_void, + } + + #[allow(dead_code)] + impl $cb { + /// Creates a new `$cb`. Returns `Err(CL_INVALID_VALUE)` if `func` is `None`. + /// + /// # SAFETY: + /// + /// If `func` is `None`, there are no safety requirements. Otherwise: + /// + /// - `func` must be a thread-safe fn. + /// - Passing `data` as the last parameter to `func` must not cause unsoundness. + pub unsafe fn new(func: Option<$fn_alias>, data: *mut c_void) -> CLResult<Self> { + let Some(func) = func else { + return Err(CL_INVALID_VALUE); + }; + Ok(Self { func, data }) + } + + /// Creates a new Option(`$cb`). Returns: + /// - `Ok(Some($cb)) if `func` is `Some(_)`. + /// - `Ok(None)` if `func` is `None` and `data` is `null`. + /// - `Err(CL_INVALID_VALUE)` if `func` is `None` and `data` is not `null`. + /// + /// # SAFETY: + /// + /// The safety requirements are identical to those of [`new`]. + pub unsafe fn try_new(func: Option<$fn_alias>, data: *mut c_void) -> CLResult<Option<Self>> { + let Some(func) = func else { + return if data.is_null() { + Ok(None) + } else { + Err(CL_INVALID_VALUE) + }; + }; + Ok(Some(Self { func, data })) + } + } + + unsafe impl Send for $cb {} + unsafe impl Sync for $cb {} } }
