use crate::{driver::Driver, error::CudaError};
use std::ptr::NonNull;
pub(crate) fn validate_non_null_pinned_host_allocation(
ptr: *mut u8,
len: usize,
) -> Result<NonNull<u8>, CudaError> {
NonNull::new(ptr).ok_or(CudaError::InternalInvariant {
what: if len == 0 {
"CUDA returned null pinned host allocation"
} else {
"CUDA returned null for a nonzero pinned host allocation"
},
})
}
pub(crate) struct PinnedUploadStaging {
pub(crate) ptr: *mut u8,
pub(crate) len: usize,
}
impl PinnedUploadStaging {
pub(crate) fn from_raw(ptr: *mut u8, len: usize) -> Result<Self, CudaError> {
let ptr = validate_non_null_pinned_host_allocation(ptr, len)?;
Ok(Self {
ptr: ptr.as_ptr(),
len,
})
}
pub(crate) fn as_slice(&self) -> &[u8] {
if self.len == 0 {
&[]
} else {
unsafe { std::slice::from_raw_parts(self.ptr.cast_const(), self.len) }
}
}
pub(crate) fn as_mut_slice(&mut self) -> &mut [u8] {
if self.len == 0 {
&mut []
} else {
unsafe { std::slice::from_raw_parts_mut(self.ptr, self.len) }
}
}
pub(crate) fn free(&mut self, driver: &Driver) -> Result<(), CudaError> {
if self.ptr.is_null() {
return Ok(());
}
driver.check("cuMemFreeHost", unsafe {
(driver.cu_mem_free_host)(self.ptr.cast())
})?;
self.ptr = std::ptr::null_mut();
self.len = 0;
Ok(())
}
}
unsafe impl Send for PinnedUploadStaging {}
#[cfg(test)]
mod tests;