1#![warn(missing_debug_implementations)]
18
19use core::ffi::c_void;
20
21use baracuda_cufile_sys::{cufile, CUfileDescr_t, CUfileError_t, CUfileHandle_t, CUfileOpError};
22
23pub type Error = baracuda_core::Error<CUfileOpError>;
25pub type Result<T, E = Error> = core::result::Result<T, E>;
27
28fn check(rc: CUfileError_t) -> Result<()> {
29 if rc.err.0 == 0 {
30 Ok(())
31 } else {
32 Err(Error::Status { status: rc.err })
33 }
34}
35
36pub fn probe() -> Result<()> {
38 cufile()?;
39 Ok(())
40}
41
42pub fn version() -> Result<i32> {
44 let c = cufile()?;
45 let cu = c.cu_file_get_version()?;
46 let mut v: core::ffi::c_int = 0;
47 check(unsafe { cu(&mut v) })?;
48 Ok(v as i32)
49}
50
51#[derive(Debug)]
57pub struct Driver {
58 _nonsend: core::marker::PhantomData<*const ()>,
59}
60
61impl Driver {
62 pub fn open() -> Result<Self> {
65 let c = cufile()?;
66 let cu = c.cu_file_driver_open()?;
67 check(unsafe { cu() })?;
68 Ok(Self {
69 _nonsend: core::marker::PhantomData,
70 })
71 }
72
73 pub fn set_poll_mode(&self, poll: bool, poll_threshold_size: usize) -> Result<()> {
76 let c = cufile()?;
77 let cu = c.cu_file_driver_set_poll_mode()?;
78 check(unsafe { cu(poll, poll_threshold_size) })
79 }
80
81 pub fn set_max_direct_io_size_kb(&self, size_kb: usize) -> Result<()> {
83 let c = cufile()?;
84 let cu = c.cu_file_driver_set_max_direct_io_size()?;
85 check(unsafe { cu(size_kb) })
86 }
87
88 pub fn set_max_cache_size_kb(&self, size_kb: usize) -> Result<()> {
90 let c = cufile()?;
91 let cu = c.cu_file_driver_set_max_cache_size()?;
92 check(unsafe { cu(size_kb) })
93 }
94
95 pub fn set_max_pinned_mem_size_kb(&self, size_kb: usize) -> Result<()> {
97 let c = cufile()?;
98 let cu = c.cu_file_driver_set_max_pinned_mem_size()?;
99 check(unsafe { cu(size_kb) })
100 }
101
102 pub unsafe fn properties(&self, props: *mut core::ffi::c_void) -> Result<()> { unsafe {
110 let c = cufile()?;
111 let cu = c.cu_file_driver_get_properties()?;
112 check(cu(props))
113 }}
114}
115
116pub fn op_status_error_string(status: CUfileOpError) -> Result<String> {
118 let c = cufile()?;
119 let cu = c.cu_file_op_status_error()?;
120 let ptr = unsafe { cu(status) };
121 if ptr.is_null() {
122 return Ok(String::new());
123 }
124 let cstr = unsafe { core::ffi::CStr::from_ptr(ptr) };
125 Ok(cstr.to_string_lossy().into_owned())
126}
127
128impl Drop for Driver {
129 fn drop(&mut self) {
130 if let Ok(c) = cufile() {
131 if let Ok(cu) = c.cu_file_driver_close() {
132 let _ = unsafe { cu() };
133 }
134 }
135 }
136}
137
138#[derive(Debug)]
140pub struct FileHandle {
141 handle: CUfileHandle_t,
142}
143
144impl FileHandle {
145 pub unsafe fn register(fd: i32) -> Result<Self> { unsafe {
152 let c = cufile()?;
153 let cu = c.cu_file_handle_register()?;
154 let mut descr = CUfileDescr_t {
155 handle_fd: fd,
156 ..Default::default()
157 };
158 let mut h: CUfileHandle_t = core::ptr::null_mut();
159 check(cu(&mut h, &mut descr))?;
160 Ok(Self { handle: h })
161 }}
162
163 #[inline]
164 pub fn as_raw(&self) -> CUfileHandle_t {
165 self.handle
166 }
167
168 pub unsafe fn read(
177 &self,
178 dev_buf: *mut c_void,
179 size: usize,
180 file_offset: i64,
181 buf_offset: i64,
182 ) -> Result<usize> { unsafe {
183 let c = cufile()?;
184 let cu = c.cu_file_read()?;
185 let n = cu(self.handle, dev_buf, size, file_offset, buf_offset);
186 if n < 0 {
187 Err(Error::Status {
188 status: CUfileOpError(n as i32),
189 })
190 } else {
191 Ok(n as usize)
192 }
193 }}
194
195 pub unsafe fn write(
201 &self,
202 dev_buf: *const c_void,
203 size: usize,
204 file_offset: i64,
205 buf_offset: i64,
206 ) -> Result<usize> { unsafe {
207 let c = cufile()?;
208 let cu = c.cu_file_write()?;
209 let n = cu(self.handle, dev_buf, size, file_offset, buf_offset);
210 if n < 0 {
211 Err(Error::Status {
212 status: CUfileOpError(n as i32),
213 })
214 } else {
215 Ok(n as usize)
216 }
217 }}
218}
219
220impl Drop for FileHandle {
221 fn drop(&mut self) {
222 if self.handle.is_null() {
223 return;
224 }
225 if let Ok(c) = cufile() {
226 if let Ok(cu) = c.cu_file_handle_deregister() {
227 unsafe { cu(self.handle) };
228 }
229 }
230 }
231}
232
233#[derive(Debug)]
236pub struct BufRegistration {
237 ptr: *mut c_void,
238 _marker: core::marker::PhantomData<*const ()>,
239}
240
241impl BufRegistration {
242 pub unsafe fn register(dev_ptr: *mut c_void, length: usize, flags: i32) -> Result<Self> { unsafe {
250 let c = cufile()?;
251 let cu = c.cu_file_buf_register()?;
252 check(cu(dev_ptr, length, flags))?;
253 Ok(Self {
254 ptr: dev_ptr,
255 _marker: core::marker::PhantomData,
256 })
257 }}
258}
259
260impl Drop for BufRegistration {
261 fn drop(&mut self) {
262 if let Ok(c) = cufile() {
263 if let Ok(cu) = c.cu_file_buf_deregister() {
264 let _ = unsafe { cu(self.ptr) };
265 }
266 }
267 }
268}
269
270#[derive(Debug)]
277pub struct StreamRegistration {
278 stream: *mut c_void,
279}
280
281impl StreamRegistration {
282 pub unsafe fn register(stream: *mut c_void, flags: u32) -> Result<Self> { unsafe {
288 let c = cufile()?;
289 let cu = c.cu_file_stream_register()?;
290 check(cu(stream, flags))?;
291 Ok(Self { stream })
292 }}
293}
294
295impl Drop for StreamRegistration {
296 fn drop(&mut self) {
297 if let Ok(c) = cufile() {
298 if let Ok(cu) = c.cu_file_stream_deregister() {
299 let _ = unsafe { cu(self.stream) };
300 }
301 }
302 }
303}
304
305impl FileHandle {
306 #[allow(clippy::too_many_arguments)]
316 pub unsafe fn read_async(
317 &self,
318 dev_buf: *mut c_void,
319 size_p: *mut usize,
320 file_offset_p: *mut i64,
321 buf_offset_p: *mut i64,
322 bytes_read: *mut isize,
323 stream: *mut c_void,
324 ) -> Result<()> { unsafe {
325 let c = cufile()?;
326 let cu = c.cu_file_read_async()?;
327 check(cu(
328 self.handle,
329 dev_buf,
330 size_p,
331 file_offset_p,
332 buf_offset_p,
333 bytes_read,
334 stream,
335 ))
336 }}
337
338 #[allow(clippy::too_many_arguments)]
344 pub unsafe fn write_async(
345 &self,
346 dev_buf: *const c_void,
347 size_p: *mut usize,
348 file_offset_p: *mut i64,
349 buf_offset_p: *mut i64,
350 bytes_written: *mut isize,
351 stream: *mut c_void,
352 ) -> Result<()> { unsafe {
353 let c = cufile()?;
354 let cu = c.cu_file_write_async()?;
355 check(cu(
356 self.handle,
357 dev_buf,
358 size_p,
359 file_offset_p,
360 buf_offset_p,
361 bytes_written,
362 stream,
363 ))
364 }}
365
366 pub fn use_count(&self) -> Result<i32> {
369 let c = cufile()?;
370 let cu = c.cu_file_use_count()?;
371 Ok(unsafe { cu(self.handle) })
372 }
373}
374
375pub use baracuda_cufile_sys::{
378 CUfileBatchHandle_t, CUfileIOEvents_t, CUfileIOParams_t, CUfileOpcode,
379};
380
381#[derive(Debug)]
384pub struct BatchIO {
385 handle: CUfileBatchHandle_t,
386}
387
388impl BatchIO {
389 pub fn new(capacity: u32) -> Result<Self> {
392 let c = cufile()?;
393 let cu = c.cu_file_batch_io_set_up()?;
394 let mut h: CUfileBatchHandle_t = core::ptr::null_mut();
395 check(unsafe { cu(&mut h, capacity) })?;
396 Ok(Self { handle: h })
397 }
398
399 pub unsafe fn submit(&self, params: &mut [CUfileIOParams_t], flags: u32) -> Result<()> { unsafe {
406 let c = cufile()?;
407 let cu = c.cu_file_batch_io_submit()?;
408 check(cu(
409 self.handle,
410 params.len() as u32,
411 params.as_mut_ptr(),
412 flags,
413 ))
414 }}
415
416 pub unsafe fn poll(&self, min_nr: u32, events: &mut [CUfileIOEvents_t]) -> Result<u32> { unsafe {
424 let c = cufile()?;
425 let cu = c.cu_file_batch_io_get_status()?;
426 let mut nr: u32 = events.len() as u32;
427 check(cu(
428 self.handle,
429 min_nr,
430 &mut nr,
431 events.as_mut_ptr(),
432 core::ptr::null_mut(),
433 ))?;
434 Ok(nr)
435 }}
436
437 pub fn cancel(&self) -> Result<()> {
439 let c = cufile()?;
440 let cu = c.cu_file_batch_io_cancel()?;
441 check(unsafe { cu(self.handle) })
442 }
443
444 #[inline]
445 pub fn as_raw(&self) -> CUfileBatchHandle_t {
446 self.handle
447 }
448}
449
450impl Drop for BatchIO {
451 fn drop(&mut self) {
452 if let Ok(c) = cufile() {
453 if let Ok(cu) = c.cu_file_batch_io_destroy() {
454 let _ = unsafe { cu(self.handle) };
455 }
456 }
457 }
458}