use std::{
ffi::CStr,
os::raw::{c_char, c_int},
};
use thiserror::Error;
#[link(name = "cudart")]
extern "C" {
fn cudaGetErrorString(error: c_int) -> *const c_char;
fn cudaGetErrorName(error: c_int) -> *const c_char;
}
fn cstr_to_string(ptr: *const c_char) -> String {
if ptr.is_null() {
return "Unknown CUDA error (null pointer)".to_string();
}
unsafe { CStr::from_ptr(ptr).to_string_lossy().into_owned() }
}
pub fn get_cuda_error_name(error_code: i32) -> String {
let name_ptr = unsafe { cudaGetErrorName(error_code) };
cstr_to_string(name_ptr)
}
pub fn get_cuda_error_string(error_code: i32) -> String {
let str_ptr = unsafe { cudaGetErrorString(error_code) };
cstr_to_string(str_ptr)
}
#[derive(Error, Debug)]
#[error("{message} ({name})")]
pub struct CudaError {
pub code: i32,
pub name: String,
pub message: String,
}
impl CudaError {
pub fn new(code: i32) -> Self {
CudaError {
code,
name: get_cuda_error_name(code),
message: get_cuda_error_string(code),
}
}
pub fn from_result(code: i32) -> Result<(), Self> {
if code == 0 {
Ok(())
} else {
Err(Self::new(code))
}
}
#[inline]
pub fn is_out_of_memory(&self) -> bool {
self.code == 2
}
}
#[inline]
pub fn check(code: i32) -> Result<(), CudaError> {
CudaError::from_result(code)
}
#[derive(Error, Debug)]
pub enum MemoryError {
#[error(transparent)]
Cuda(#[from] CudaError),
#[error("Attempted to free null pointer")]
NullPointer,
#[error("Attempted to free untracked pointer")]
UntrackedPointer,
#[error("Failed to acquire memory manager lock")]
LockError,
#[error("Invalid memory size: {size}")]
InvalidMemorySize { size: usize },
#[error(
"Requested VPMM allocation {requested} exceeds reserved VA chunk size {va_size} bytes"
)]
RequestedExceedsVaChunk { requested: usize, va_size: usize },
#[error(
"Out of memory in pool (size requested: {requested} bytes, available: {available} bytes)"
)]
OutOfMemory { requested: usize, available: usize },
#[error("Invalid pointer: pointer not found in allocation table")]
InvalidPointer,
#[error("Failed to reserve virtual address space (bytes: {size}, page size: {page_size})")]
ReserveFailed { size: usize, page_size: usize },
}
#[derive(Error, Debug)]
pub enum MemCopyError {
#[error(transparent)]
Cuda(#[from] CudaError),
#[error("Size mismatch in {operation}: src len={src_len}, dst len={dst_len}")]
SizeMismatch {
operation: &'static str,
src_len: usize,
dst_len: usize,
},
}