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 <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25669>
This commit is contained in:
LingMan 2023-10-11 21:26:05 +02:00 committed by Marge Bot
parent 157c743a27
commit e461944060

View file

@ -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 {}
}
}