#![warn(missing_debug_implementations)]
use core::ffi::c_void;
use baracuda_cufile_sys::{cufile, CUfileDescr_t, CUfileError_t, CUfileHandle_t, CUfileOpError};
pub type Error = baracuda_core::Error<CUfileOpError>;
pub type Result<T, E = Error> = core::result::Result<T, E>;
fn check(rc: CUfileError_t) -> Result<()> {
if rc.err.0 == 0 {
Ok(())
} else {
Err(Error::Status { status: rc.err })
}
}
pub fn probe() -> Result<()> {
cufile()?;
Ok(())
}
pub fn version() -> Result<i32> {
let c = cufile()?;
let cu = c.cu_file_get_version()?;
let mut v: core::ffi::c_int = 0;
check(unsafe { cu(&mut v) })?;
Ok(v as i32)
}
#[derive(Debug)]
pub struct Driver {
_nonsend: core::marker::PhantomData<*const ()>,
}
impl Driver {
pub fn open() -> Result<Self> {
let c = cufile()?;
let cu = c.cu_file_driver_open()?;
check(unsafe { cu() })?;
Ok(Self {
_nonsend: core::marker::PhantomData,
})
}
pub fn set_poll_mode(&self, poll: bool, poll_threshold_size: usize) -> Result<()> {
let c = cufile()?;
let cu = c.cu_file_driver_set_poll_mode()?;
check(unsafe { cu(poll, poll_threshold_size) })
}
pub fn set_max_direct_io_size_kb(&self, size_kb: usize) -> Result<()> {
let c = cufile()?;
let cu = c.cu_file_driver_set_max_direct_io_size()?;
check(unsafe { cu(size_kb) })
}
pub fn set_max_cache_size_kb(&self, size_kb: usize) -> Result<()> {
let c = cufile()?;
let cu = c.cu_file_driver_set_max_cache_size()?;
check(unsafe { cu(size_kb) })
}
pub fn set_max_pinned_mem_size_kb(&self, size_kb: usize) -> Result<()> {
let c = cufile()?;
let cu = c.cu_file_driver_set_max_pinned_mem_size()?;
check(unsafe { cu(size_kb) })
}
pub unsafe fn properties(&self, props: *mut core::ffi::c_void) -> Result<()> { unsafe {
let c = cufile()?;
let cu = c.cu_file_driver_get_properties()?;
check(cu(props))
}}
}
pub fn op_status_error_string(status: CUfileOpError) -> Result<String> {
let c = cufile()?;
let cu = c.cu_file_op_status_error()?;
let ptr = unsafe { cu(status) };
if ptr.is_null() {
return Ok(String::new());
}
let cstr = unsafe { core::ffi::CStr::from_ptr(ptr) };
Ok(cstr.to_string_lossy().into_owned())
}
impl Drop for Driver {
fn drop(&mut self) {
if let Ok(c) = cufile() {
if let Ok(cu) = c.cu_file_driver_close() {
let _ = unsafe { cu() };
}
}
}
}
#[derive(Debug)]
pub struct FileHandle {
handle: CUfileHandle_t,
}
impl FileHandle {
pub unsafe fn register(fd: i32) -> Result<Self> { unsafe {
let c = cufile()?;
let cu = c.cu_file_handle_register()?;
let mut descr = CUfileDescr_t {
handle_fd: fd,
..Default::default()
};
let mut h: CUfileHandle_t = core::ptr::null_mut();
check(cu(&mut h, &mut descr))?;
Ok(Self { handle: h })
}}
#[inline]
pub fn as_raw(&self) -> CUfileHandle_t {
self.handle
}
pub unsafe fn read(
&self,
dev_buf: *mut c_void,
size: usize,
file_offset: i64,
buf_offset: i64,
) -> Result<usize> { unsafe {
let c = cufile()?;
let cu = c.cu_file_read()?;
let n = cu(self.handle, dev_buf, size, file_offset, buf_offset);
if n < 0 {
Err(Error::Status {
status: CUfileOpError(n as i32),
})
} else {
Ok(n as usize)
}
}}
pub unsafe fn write(
&self,
dev_buf: *const c_void,
size: usize,
file_offset: i64,
buf_offset: i64,
) -> Result<usize> { unsafe {
let c = cufile()?;
let cu = c.cu_file_write()?;
let n = cu(self.handle, dev_buf, size, file_offset, buf_offset);
if n < 0 {
Err(Error::Status {
status: CUfileOpError(n as i32),
})
} else {
Ok(n as usize)
}
}}
}
impl Drop for FileHandle {
fn drop(&mut self) {
if self.handle.is_null() {
return;
}
if let Ok(c) = cufile() {
if let Ok(cu) = c.cu_file_handle_deregister() {
unsafe { cu(self.handle) };
}
}
}
}
#[derive(Debug)]
pub struct BufRegistration {
ptr: *mut c_void,
_marker: core::marker::PhantomData<*const ()>,
}
impl BufRegistration {
pub unsafe fn register(dev_ptr: *mut c_void, length: usize, flags: i32) -> Result<Self> { unsafe {
let c = cufile()?;
let cu = c.cu_file_buf_register()?;
check(cu(dev_ptr, length, flags))?;
Ok(Self {
ptr: dev_ptr,
_marker: core::marker::PhantomData,
})
}}
}
impl Drop for BufRegistration {
fn drop(&mut self) {
if let Ok(c) = cufile() {
if let Ok(cu) = c.cu_file_buf_deregister() {
let _ = unsafe { cu(self.ptr) };
}
}
}
}
#[derive(Debug)]
pub struct StreamRegistration {
stream: *mut c_void,
}
impl StreamRegistration {
pub unsafe fn register(stream: *mut c_void, flags: u32) -> Result<Self> { unsafe {
let c = cufile()?;
let cu = c.cu_file_stream_register()?;
check(cu(stream, flags))?;
Ok(Self { stream })
}}
}
impl Drop for StreamRegistration {
fn drop(&mut self) {
if let Ok(c) = cufile() {
if let Ok(cu) = c.cu_file_stream_deregister() {
let _ = unsafe { cu(self.stream) };
}
}
}
}
impl FileHandle {
#[allow(clippy::too_many_arguments)]
pub unsafe fn read_async(
&self,
dev_buf: *mut c_void,
size_p: *mut usize,
file_offset_p: *mut i64,
buf_offset_p: *mut i64,
bytes_read: *mut isize,
stream: *mut c_void,
) -> Result<()> { unsafe {
let c = cufile()?;
let cu = c.cu_file_read_async()?;
check(cu(
self.handle,
dev_buf,
size_p,
file_offset_p,
buf_offset_p,
bytes_read,
stream,
))
}}
#[allow(clippy::too_many_arguments)]
pub unsafe fn write_async(
&self,
dev_buf: *const c_void,
size_p: *mut usize,
file_offset_p: *mut i64,
buf_offset_p: *mut i64,
bytes_written: *mut isize,
stream: *mut c_void,
) -> Result<()> { unsafe {
let c = cufile()?;
let cu = c.cu_file_write_async()?;
check(cu(
self.handle,
dev_buf,
size_p,
file_offset_p,
buf_offset_p,
bytes_written,
stream,
))
}}
pub fn use_count(&self) -> Result<i32> {
let c = cufile()?;
let cu = c.cu_file_use_count()?;
Ok(unsafe { cu(self.handle) })
}
}
pub use baracuda_cufile_sys::{
CUfileBatchHandle_t, CUfileIOEvents_t, CUfileIOParams_t, CUfileOpcode,
};
#[derive(Debug)]
pub struct BatchIO {
handle: CUfileBatchHandle_t,
}
impl BatchIO {
pub fn new(capacity: u32) -> Result<Self> {
let c = cufile()?;
let cu = c.cu_file_batch_io_set_up()?;
let mut h: CUfileBatchHandle_t = core::ptr::null_mut();
check(unsafe { cu(&mut h, capacity) })?;
Ok(Self { handle: h })
}
pub unsafe fn submit(&self, params: &mut [CUfileIOParams_t], flags: u32) -> Result<()> { unsafe {
let c = cufile()?;
let cu = c.cu_file_batch_io_submit()?;
check(cu(
self.handle,
params.len() as u32,
params.as_mut_ptr(),
flags,
))
}}
pub unsafe fn poll(&self, min_nr: u32, events: &mut [CUfileIOEvents_t]) -> Result<u32> { unsafe {
let c = cufile()?;
let cu = c.cu_file_batch_io_get_status()?;
let mut nr: u32 = events.len() as u32;
check(cu(
self.handle,
min_nr,
&mut nr,
events.as_mut_ptr(),
core::ptr::null_mut(),
))?;
Ok(nr)
}}
pub fn cancel(&self) -> Result<()> {
let c = cufile()?;
let cu = c.cu_file_batch_io_cancel()?;
check(unsafe { cu(self.handle) })
}
#[inline]
pub fn as_raw(&self) -> CUfileBatchHandle_t {
self.handle
}
}
impl Drop for BatchIO {
fn drop(&mut self) {
if let Ok(c) = cufile() {
if let Ok(cu) = c.cu_file_batch_io_destroy() {
let _ = unsafe { cu(self.handle) };
}
}
}
}