mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-08-02 14:57:43 +03:00
Move FromCuda trait into zluda_common
This commit is contained in:
5
Cargo.lock
generated
5
Cargo.lock
generated
@ -1793,6 +1793,7 @@ dependencies = [
|
||||
"rustc-hash 1.1.0",
|
||||
"tempfile",
|
||||
"winapi",
|
||||
"zluda_common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1828,6 +1829,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "zluda_common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cuda_types",
|
||||
"hip_runtime-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zluda_dnn"
|
||||
|
@ -22,6 +22,8 @@ lz4-sys = "1.9"
|
||||
tempfile = "3"
|
||||
paste = "1.0"
|
||||
rustc-hash = "1.1"
|
||||
dtor = "0.0.6"
|
||||
zluda_common = { path = "../zluda_common" }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["heapapi", "std"] }
|
||||
@ -34,4 +36,4 @@ dtor = "0.0.6"
|
||||
linux_symlinks = [
|
||||
"libcuda.so",
|
||||
"libcuda.so.1",
|
||||
]
|
||||
]
|
||||
|
@ -1,8 +1,9 @@
|
||||
use super::{module, FromCuda, ZludaObject};
|
||||
use super::module;
|
||||
use cuda_types::cuda::*;
|
||||
use hip_runtime_sys::*;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use std::{cell::RefCell, ffi::c_void, ptr, sync::Mutex};
|
||||
use zluda_common::{FromCuda, ZludaObject};
|
||||
|
||||
thread_local! {
|
||||
pub(crate) static STACK: RefCell<Vec<(CUcontext, hipDevice_t)>> = RefCell::new(Vec::new());
|
||||
@ -48,7 +49,7 @@ impl ContextState {
|
||||
self.flags = 0;
|
||||
// drop all modules and return first error if any
|
||||
let result = self.modules.drain().fold(Ok(()), |res: CUresult, hmod| {
|
||||
match (res, super::drop_checked::<module::Module>(hmod)) {
|
||||
match (res, zluda_common::drop_checked::<module::Module>(hmod)) {
|
||||
(Err(e), _) => Err(e),
|
||||
(_, Err(e)) => Err(e),
|
||||
_ => Ok(()),
|
||||
@ -196,7 +197,7 @@ pub(crate) unsafe fn create_v2(
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn destroy_v2(ctx: CUcontext) -> CUresult {
|
||||
super::drop_checked::<Context>(ctx)
|
||||
zluda_common::drop_checked::<Context>(ctx)
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn pop_current_v2(ctx: &mut CUcontext) -> CUresult {
|
||||
|
@ -1,8 +1,8 @@
|
||||
use super::{FromCuda, LiveCheck};
|
||||
use crate::r#impl::{context, device};
|
||||
use comgr::Comgr;
|
||||
use cuda_types::cuda::*;
|
||||
use hip_runtime_sys::*;
|
||||
use zluda_common::{FromCuda, LiveCheck};
|
||||
use std::{
|
||||
ffi::{c_void, CStr, CString},
|
||||
mem, ptr, slice,
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::{module, ZludaObject};
|
||||
use super::module;
|
||||
use cuda_types::cuda::*;
|
||||
use hip_runtime_sys::*;
|
||||
use zluda_common::ZludaObject;
|
||||
|
||||
pub(crate) struct Library {
|
||||
base: hipModule_t,
|
||||
@ -36,7 +37,7 @@ pub(crate) fn load_data(
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn unload(library: CUlibrary) -> CUresult {
|
||||
super::drop_checked::<Library>(library)
|
||||
zluda_common::drop_checked::<Library>(library)
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn get_module(out: &mut CUmodule, library: &Library) -> CUresult {
|
||||
|
@ -1,10 +1,5 @@
|
||||
use cuda_types::cuda::*;
|
||||
use hip_runtime_sys::*;
|
||||
use std::{
|
||||
ffi::CStr,
|
||||
mem::{self, ManuallyDrop, MaybeUninit},
|
||||
ptr,
|
||||
};
|
||||
use zluda_common::from_cuda_object;
|
||||
|
||||
pub(super) mod context;
|
||||
pub(super) mod device;
|
||||
@ -26,244 +21,4 @@ pub(crate) fn unimplemented() -> CUresult {
|
||||
CUresult::ERROR_NOT_SUPPORTED
|
||||
}
|
||||
|
||||
pub(crate) trait CudaErrorType {
|
||||
const INVALID_VALUE: Self;
|
||||
const NOT_SUPPORTED: Self;
|
||||
}
|
||||
|
||||
impl CudaErrorType for CUerror {
|
||||
const INVALID_VALUE: Self = Self::INVALID_VALUE;
|
||||
const NOT_SUPPORTED: Self = Self::NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
pub(crate) trait FromCuda<'a, T, E: CudaErrorType>: Sized {
|
||||
fn from_cuda(t: &'a T) -> Result<Self, E>;
|
||||
}
|
||||
|
||||
macro_rules! from_cuda_nop {
|
||||
($($type_:ty),*) => {
|
||||
$(
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, $type_, E> for $type_ {
|
||||
fn from_cuda(x: &'a $type_) -> Result<Self, E> {
|
||||
Ok(*x)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *mut $type_, E> for &'a mut $type_ {
|
||||
fn from_cuda(x: &'a *mut $type_) -> Result<Self, E> {
|
||||
match unsafe { x.as_mut() } {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(E::INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *const $type_, E> for &'a $type_ {
|
||||
fn from_cuda(x: &'a *const $type_) -> Result<Self, E> {
|
||||
match unsafe { x.as_ref() } {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(E::INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *mut $type_, E> for Option<&'a mut $type_> {
|
||||
fn from_cuda(x: &'a *mut $type_) -> Result<Self, E> {
|
||||
Ok(unsafe { x.as_mut() })
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! from_cuda_transmute {
|
||||
($($from:ty => $to:ty),*) => {
|
||||
$(
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, $from, E> for $to {
|
||||
fn from_cuda(x: &'a $from) -> Result<Self, E> {
|
||||
Ok(unsafe { std::mem::transmute(*x) })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *mut $from, E> for &'a mut $to {
|
||||
fn from_cuda(x: &'a *mut $from) -> Result<Self, E> {
|
||||
match unsafe { x.cast::<$to>().as_mut() } {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(E::INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *mut $from, E> for * mut $to {
|
||||
fn from_cuda(x: &'a *mut $from) -> Result<Self, E> {
|
||||
Ok(x.cast::<$to>())
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! from_cuda_object {
|
||||
($($type_:ty),*) => {
|
||||
$(
|
||||
impl<'a> FromCuda<'a, <$type_ as ZludaObject>::CudaHandle, <$type_ as ZludaObject>::Error> for <$type_ as ZludaObject>::CudaHandle {
|
||||
fn from_cuda(handle: &'a <$type_ as ZludaObject>::CudaHandle) -> Result<<$type_ as ZludaObject>::CudaHandle, <$type_ as ZludaObject>::Error> {
|
||||
Ok(*handle)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromCuda<'a, *mut <$type_ as ZludaObject>::CudaHandle, <$type_ as ZludaObject>::Error> for &'a mut <$type_ as ZludaObject>::CudaHandle {
|
||||
fn from_cuda(handle: &'a *mut <$type_ as ZludaObject>::CudaHandle) -> Result<&'a mut <$type_ as ZludaObject>::CudaHandle, <$type_ as ZludaObject>::Error> {
|
||||
match unsafe { handle.as_mut() } {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(<$type_ as ZludaObject>::Error::INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromCuda<'a, <$type_ as ZludaObject>::CudaHandle, <$type_ as ZludaObject>::Error> for &'a $type_ {
|
||||
fn from_cuda(handle: &'a <$type_ as ZludaObject>::CudaHandle) -> Result<&'a $type_, <$type_ as ZludaObject>::Error> {
|
||||
Ok(as_ref(handle).as_result()?)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
from_cuda_nop!(
|
||||
*mut i8,
|
||||
*mut i32,
|
||||
*mut usize,
|
||||
*const ::core::ffi::c_void,
|
||||
*const ::core::ffi::c_char,
|
||||
*mut ::core::ffi::c_void,
|
||||
*mut *mut ::core::ffi::c_void,
|
||||
u8,
|
||||
i32,
|
||||
u32,
|
||||
u64,
|
||||
usize,
|
||||
cuda_types::cuda::CUdevprop,
|
||||
CUdevice_attribute,
|
||||
CUdriverProcAddressQueryResult,
|
||||
CUjit_option,
|
||||
CUlibraryOption,
|
||||
CUmoduleLoadingMode,
|
||||
CUuuid
|
||||
);
|
||||
from_cuda_transmute!(
|
||||
CUuuid => hipUUID,
|
||||
CUfunction => hipFunction_t,
|
||||
CUfunction_attribute => hipFunction_attribute,
|
||||
CUstream => hipStream_t,
|
||||
CUpointer_attribute => hipPointer_attribute,
|
||||
CUdeviceptr_v2 => hipDeviceptr_t
|
||||
);
|
||||
from_cuda_object!(module::Module, context::Context, library::Library);
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, CUlimit, E> for hipLimit_t {
|
||||
fn from_cuda(limit: &'a CUlimit) -> Result<Self, E> {
|
||||
Ok(match *limit {
|
||||
CUlimit::CU_LIMIT_STACK_SIZE => hipLimit_t::hipLimitStackSize,
|
||||
CUlimit::CU_LIMIT_PRINTF_FIFO_SIZE => hipLimit_t::hipLimitPrintfFifoSize,
|
||||
CUlimit::CU_LIMIT_MALLOC_HEAP_SIZE => hipLimit_t::hipLimitMallocHeapSize,
|
||||
_ => return Err(E::NOT_SUPPORTED),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *const ::core::ffi::c_char, E> for &CStr {
|
||||
fn from_cuda(s: &'a *const ::core::ffi::c_char) -> Result<Self, E> {
|
||||
if *s != ptr::null() {
|
||||
Ok(unsafe { CStr::from_ptr(*s) })
|
||||
} else {
|
||||
Err(E::INVALID_VALUE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *const ::core::ffi::c_void, E>
|
||||
for &'a ::core::ffi::c_void
|
||||
{
|
||||
fn from_cuda(x: &'a *const ::core::ffi::c_void) -> Result<Self, E> {
|
||||
match unsafe { x.as_ref() } {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(E::INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait ZludaObject: Sized + Send + Sync {
|
||||
const COOKIE: usize;
|
||||
const LIVENESS_FAIL: Self::Error = Self::Error::INVALID_VALUE;
|
||||
|
||||
type Error: CudaErrorType;
|
||||
type CudaHandle: Sized;
|
||||
|
||||
fn drop_checked(&mut self) -> Result<(), Self::Error>;
|
||||
|
||||
fn wrap(self) -> Self::CudaHandle {
|
||||
unsafe { mem::transmute_copy(&LiveCheck::wrap(self)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct LiveCheck<T: ZludaObject> {
|
||||
cookie: usize,
|
||||
data: MaybeUninit<T>,
|
||||
}
|
||||
|
||||
impl<T: ZludaObject> LiveCheck<T> {
|
||||
fn new(data: T) -> Self {
|
||||
LiveCheck {
|
||||
cookie: T::COOKIE,
|
||||
data: MaybeUninit::new(data),
|
||||
}
|
||||
}
|
||||
|
||||
fn as_handle(&self) -> T::CudaHandle {
|
||||
unsafe { mem::transmute_copy(&self) }
|
||||
}
|
||||
|
||||
fn wrap(data: T) -> *mut Self {
|
||||
Box::into_raw(Box::new(Self::new(data)))
|
||||
}
|
||||
|
||||
fn as_result(&self) -> Result<&T, T::Error> {
|
||||
if self.cookie == T::COOKIE {
|
||||
Ok(unsafe { self.data.assume_init_ref() })
|
||||
} else {
|
||||
Err(T::LIVENESS_FAIL)
|
||||
}
|
||||
}
|
||||
|
||||
// This looks like nonsense, but it's not. There are two cases:
|
||||
// Err(CUerror) -> meaning that the object is invalid, this pointer does not point into valid memory
|
||||
// Ok(maybe_error) -> meaning that the object is valid, we dropped everything, but there *might*
|
||||
// an error in the underlying runtime that we want to propagate
|
||||
#[must_use]
|
||||
fn drop_checked(&mut self) -> Result<Result<(), T::Error>, T::Error> {
|
||||
if self.cookie == T::COOKIE {
|
||||
self.cookie = 0;
|
||||
let result = unsafe { self.data.assume_init_mut().drop_checked() };
|
||||
unsafe { MaybeUninit::assume_init_drop(&mut self.data) };
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(T::LIVENESS_FAIL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ref<'a, T: ZludaObject>(
|
||||
handle: &'a T::CudaHandle,
|
||||
) -> &'a ManuallyDrop<Box<LiveCheck<T>>> {
|
||||
unsafe { mem::transmute(handle) }
|
||||
}
|
||||
|
||||
pub fn drop_checked<T: ZludaObject>(handle: T::CudaHandle) -> Result<(), T::Error> {
|
||||
let mut wrapped_object: ManuallyDrop<Box<LiveCheck<T>>> =
|
||||
unsafe { mem::transmute_copy(&handle) };
|
||||
let underlying_error = LiveCheck::drop_checked(&mut wrapped_object)?;
|
||||
unsafe { ManuallyDrop::drop(&mut wrapped_object) };
|
||||
underlying_error
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{driver, ZludaObject};
|
||||
use super::driver;
|
||||
use cuda_types::{
|
||||
cuda::*,
|
||||
dark_api::{FatbinFileHeader, FatbincWrapper},
|
||||
@ -6,6 +6,7 @@ use cuda_types::{
|
||||
use dark_api::fatbin::Fatbin;
|
||||
use hip_runtime_sys::*;
|
||||
use std::{ffi::CStr, mem};
|
||||
use zluda_common::ZludaObject;
|
||||
|
||||
pub(crate) struct Module {
|
||||
pub(crate) base: hipModule_t,
|
||||
@ -69,7 +70,9 @@ pub(crate) fn load_hip_module(image: *const std::ffi::c_void) -> Result<hipModul
|
||||
unsafe { hipCtxGetDevice(&mut dev) }?;
|
||||
let mut props = unsafe { mem::zeroed() };
|
||||
unsafe { hipGetDevicePropertiesR0600(&mut props, dev) }?;
|
||||
let attributes = ptx::Attributes { clock_rate: props.clockRate as u32 };
|
||||
let attributes = ptx::Attributes {
|
||||
clock_rate: props.clockRate as u32,
|
||||
};
|
||||
let llvm_module = ptx::to_llvm_module(ast, attributes).map_err(|_| CUerror::UNKNOWN)?;
|
||||
let elf_module = comgr::compile_bitcode(
|
||||
&global_state.comgr,
|
||||
@ -91,8 +94,7 @@ pub(crate) fn load_data(module: &mut CUmodule, image: &std::ffi::c_void) -> CUre
|
||||
}
|
||||
|
||||
pub(crate) fn unload(hmod: CUmodule) -> CUresult {
|
||||
super::drop_checked::<Module>(hmod)
|
||||
|
||||
zluda_common::drop_checked::<Module>(hmod)
|
||||
}
|
||||
|
||||
pub(crate) fn get_function(
|
||||
|
@ -40,7 +40,7 @@ macro_rules! implemented {
|
||||
if !initialized() {
|
||||
return Err(CUerror::DEINITIALIZED);
|
||||
}
|
||||
cuda_macros::cuda_normalize_fn!( crate::r#impl::$fn_name ) ($(crate::r#impl::FromCuda::<_, CUerror>::from_cuda(&$arg_id)?),*)?;
|
||||
cuda_macros::cuda_normalize_fn!( crate::r#impl::$fn_name ) ($(zluda_common::FromCuda::<_, CUerror>::from_cuda(&$arg_id)?),*)?;
|
||||
Ok(())
|
||||
}
|
||||
)*
|
||||
@ -57,7 +57,7 @@ macro_rules! implemented_in_function {
|
||||
if !initialized() {
|
||||
return Err(CUerror::DEINITIALIZED);
|
||||
}
|
||||
cuda_macros::cuda_normalize_fn!( crate::r#impl::function::$fn_name ) ($(crate::r#impl::FromCuda::<_, CUerror>::from_cuda(&$arg_id)?),*)?;
|
||||
cuda_macros::cuda_normalize_fn!( crate::r#impl::function::$fn_name ) ($(zluda_common::FromCuda::<_, CUerror>::from_cuda(&$arg_id)?),*)?;
|
||||
Ok(())
|
||||
}
|
||||
)*
|
||||
|
@ -5,3 +5,5 @@ authors = ["Violet <c01368481@gmail.com>"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cuda_types = { "0.0.0", path = "../cuda_types" }
|
||||
hip_runtime-sys = { "0.0.0", path = "../ext/hip_runtime-sys" }
|
||||
|
@ -1,5 +1,238 @@
|
||||
pub fn add(left: u64, right: u64) -> u64 {
|
||||
left + right
|
||||
use cuda_types::cuda::*;
|
||||
use hip_runtime_sys::*;
|
||||
use std::{
|
||||
ffi::CStr,
|
||||
mem::{self, ManuallyDrop, MaybeUninit},
|
||||
ptr,
|
||||
};
|
||||
|
||||
pub trait CudaErrorType {
|
||||
const INVALID_VALUE: Self;
|
||||
const NOT_SUPPORTED: Self;
|
||||
}
|
||||
|
||||
impl CudaErrorType for CUerror {
|
||||
const INVALID_VALUE: Self = Self::INVALID_VALUE;
|
||||
const NOT_SUPPORTED: Self = Self::NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
pub trait FromCuda<'a, T, E: CudaErrorType>: Sized {
|
||||
fn from_cuda(t: &'a T) -> Result<Self, E>;
|
||||
}
|
||||
|
||||
macro_rules! from_cuda_nop {
|
||||
($($type_:ty),*) => {
|
||||
$(
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, $type_, E> for $type_ {
|
||||
fn from_cuda(x: &'a $type_) -> Result<Self, E> {
|
||||
Ok(*x)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *mut $type_, E> for &'a mut $type_ {
|
||||
fn from_cuda(x: &'a *mut $type_) -> Result<Self, E> {
|
||||
match unsafe { x.as_mut() } {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(E::INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *const $type_, E> for &'a $type_ {
|
||||
fn from_cuda(x: &'a *const $type_) -> Result<Self, E> {
|
||||
match unsafe { x.as_ref() } {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(E::INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *mut $type_, E> for Option<&'a mut $type_> {
|
||||
fn from_cuda(x: &'a *mut $type_) -> Result<Self, E> {
|
||||
Ok(unsafe { x.as_mut() })
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! from_cuda_transmute {
|
||||
($($from:ty => $to:ty),*) => {
|
||||
$(
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, $from, E> for $to {
|
||||
fn from_cuda(x: &'a $from) -> Result<Self, E> {
|
||||
Ok(unsafe { std::mem::transmute(*x) })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *mut $from, E> for &'a mut $to {
|
||||
fn from_cuda(x: &'a *mut $from) -> Result<Self, E> {
|
||||
match unsafe { x.cast::<$to>().as_mut() } {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(E::INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *mut $from, E> for * mut $to {
|
||||
fn from_cuda(x: &'a *mut $from) -> Result<Self, E> {
|
||||
Ok(x.cast::<$to>())
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! from_cuda_object {
|
||||
($($type_:ty),*) => {
|
||||
$(
|
||||
impl<'a> zluda_common::FromCuda<'a, <$type_ as zluda_common::ZludaObject>::CudaHandle, <$type_ as zluda_common::ZludaObject>::Error> for &'a $type_ {
|
||||
fn from_cuda(handle: &'a <$type_ as zluda_common::ZludaObject>::CudaHandle) -> Result<&'a $type_, <$type_ as zluda_common::ZludaObject>::Error> {
|
||||
Ok(zluda_common::as_ref(handle).as_result()?)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
from_cuda_nop!(
|
||||
*mut i8,
|
||||
*mut i32,
|
||||
*mut usize,
|
||||
*const ::core::ffi::c_void,
|
||||
*const ::core::ffi::c_char,
|
||||
*mut ::core::ffi::c_void,
|
||||
*mut *mut ::core::ffi::c_void,
|
||||
u8,
|
||||
i32,
|
||||
u32,
|
||||
u64,
|
||||
usize,
|
||||
cuda_types::cuda::CUdevprop,
|
||||
CUdevice_attribute,
|
||||
CUdriverProcAddressQueryResult,
|
||||
CUjit_option,
|
||||
CUlibraryOption,
|
||||
CUmoduleLoadingMode,
|
||||
CUuuid,
|
||||
|
||||
CUlibrary,
|
||||
CUmodule,
|
||||
CUcontext
|
||||
);
|
||||
from_cuda_transmute!(
|
||||
CUuuid => hipUUID,
|
||||
CUfunction => hipFunction_t,
|
||||
CUfunction_attribute => hipFunction_attribute,
|
||||
CUstream => hipStream_t,
|
||||
CUpointer_attribute => hipPointer_attribute,
|
||||
CUdeviceptr_v2 => hipDeviceptr_t
|
||||
);
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, CUlimit, E> for hipLimit_t {
|
||||
fn from_cuda(limit: &'a CUlimit) -> Result<Self, E> {
|
||||
Ok(match *limit {
|
||||
CUlimit::CU_LIMIT_STACK_SIZE => hipLimit_t::hipLimitStackSize,
|
||||
CUlimit::CU_LIMIT_PRINTF_FIFO_SIZE => hipLimit_t::hipLimitPrintfFifoSize,
|
||||
CUlimit::CU_LIMIT_MALLOC_HEAP_SIZE => hipLimit_t::hipLimitMallocHeapSize,
|
||||
_ => return Err(E::NOT_SUPPORTED),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *const ::core::ffi::c_char, E> for &CStr {
|
||||
fn from_cuda(s: &'a *const ::core::ffi::c_char) -> Result<Self, E> {
|
||||
if *s != ptr::null() {
|
||||
Ok(unsafe { CStr::from_ptr(*s) })
|
||||
} else {
|
||||
Err(E::INVALID_VALUE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: CudaErrorType> FromCuda<'a, *const ::core::ffi::c_void, E> for &'a ::core::ffi::c_void {
|
||||
fn from_cuda(x: &'a *const ::core::ffi::c_void) -> Result<Self, E> {
|
||||
match unsafe { x.as_ref() } {
|
||||
Some(x) => Ok(x),
|
||||
None => Err(E::INVALID_VALUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ZludaObject: Sized + Send + Sync {
|
||||
const COOKIE: usize;
|
||||
const LIVENESS_FAIL: Self::Error = Self::Error::INVALID_VALUE;
|
||||
|
||||
type Error: CudaErrorType;
|
||||
type CudaHandle: Sized;
|
||||
|
||||
fn drop_checked(&mut self) -> Result<(), Self::Error>;
|
||||
|
||||
fn wrap(self) -> Self::CudaHandle {
|
||||
unsafe { mem::transmute_copy(&LiveCheck::wrap(self)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct LiveCheck<T: ZludaObject> {
|
||||
cookie: usize,
|
||||
pub data: MaybeUninit<T>,
|
||||
}
|
||||
|
||||
impl<T: ZludaObject> LiveCheck<T> {
|
||||
pub fn new(data: T) -> Self {
|
||||
LiveCheck {
|
||||
cookie: T::COOKIE,
|
||||
data: MaybeUninit::new(data),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_handle(&self) -> T::CudaHandle {
|
||||
unsafe { mem::transmute_copy(&self) }
|
||||
}
|
||||
|
||||
fn wrap(data: T) -> *mut Self {
|
||||
Box::into_raw(Box::new(Self::new(data)))
|
||||
}
|
||||
|
||||
pub fn as_result(&self) -> Result<&T, T::Error> {
|
||||
if self.cookie == T::COOKIE {
|
||||
Ok(unsafe { self.data.assume_init_ref() })
|
||||
} else {
|
||||
Err(T::LIVENESS_FAIL)
|
||||
}
|
||||
}
|
||||
|
||||
// This looks like nonsense, but it's not. There are two cases:
|
||||
// Err(CUerror) -> meaning that the object is invalid, this pointer does not point into valid memory
|
||||
// Ok(maybe_error) -> meaning that the object is valid, we dropped everything, but there *might*
|
||||
// an error in the underlying runtime that we want to propagate
|
||||
#[must_use]
|
||||
fn drop_checked(&mut self) -> Result<Result<(), T::Error>, T::Error> {
|
||||
if self.cookie == T::COOKIE {
|
||||
self.cookie = 0;
|
||||
let result = unsafe { self.data.assume_init_mut().drop_checked() };
|
||||
unsafe { MaybeUninit::assume_init_drop(&mut self.data) };
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(T::LIVENESS_FAIL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ref<'a, T: ZludaObject>(
|
||||
handle: &'a T::CudaHandle,
|
||||
) -> &'a ManuallyDrop<Box<LiveCheck<T>>> {
|
||||
unsafe { mem::transmute(handle) }
|
||||
}
|
||||
|
||||
pub fn drop_checked<T: ZludaObject>(handle: T::CudaHandle) -> Result<(), T::Error> {
|
||||
let mut wrapped_object: ManuallyDrop<Box<LiveCheck<T>>> =
|
||||
unsafe { mem::transmute_copy(&handle) };
|
||||
let underlying_error = LiveCheck::drop_checked(&mut wrapped_object)?;
|
||||
unsafe { ManuallyDrop::drop(&mut wrapped_object) };
|
||||
underlying_error
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -8,7 +241,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
assert_eq!(4, 4);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user