1use crate::ffi;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
20pub enum CudaError {
21 #[error("CUDA: invalid value")]
24 InvalidValue,
25
26 #[error("CUDA: out of device memory")]
28 OutOfMemory,
29
30 #[error("CUDA: not initialized")]
32 NotInitialized,
33
34 #[error("CUDA: deinitialized")]
36 Deinitialized,
37
38 #[error("CUDA: profiler disabled")]
40 ProfilerDisabled,
41
42 #[error("CUDA: profiler not initialized (deprecated)")]
44 ProfilerNotInitialized,
45
46 #[error("CUDA: profiler already started (deprecated)")]
48 ProfilerAlreadyStarted,
49
50 #[error("CUDA: profiler already stopped (deprecated)")]
52 ProfilerAlreadyStopped,
53
54 #[error("CUDA: stub library loaded instead of real driver")]
57 StubLibrary,
58
59 #[error("CUDA: device unavailable")]
61 DeviceUnavailable,
62
63 #[error("CUDA: no device found")]
66 NoDevice,
67
68 #[error("CUDA: invalid device")]
70 InvalidDevice,
71
72 #[error("CUDA: device not licensed")]
74 DeviceNotLicensed,
75
76 #[error("CUDA: invalid PTX/cubin image")]
79 InvalidImage,
80
81 #[error("CUDA: invalid context")]
83 InvalidContext,
84
85 #[error("CUDA: context already current (deprecated)")]
87 ContextAlreadyCurrent,
88
89 #[error("CUDA: map failed")]
91 MapFailed,
92
93 #[error("CUDA: unmap failed")]
95 UnmapFailed,
96
97 #[error("CUDA: array is mapped")]
99 ArrayIsMapped,
100
101 #[error("CUDA: already mapped")]
103 AlreadyMapped,
104
105 #[error("CUDA: no binary for GPU")]
107 NoBinaryForGpu,
108
109 #[error("CUDA: already acquired")]
111 AlreadyAcquired,
112
113 #[error("CUDA: not mapped")]
115 NotMapped,
116
117 #[error("CUDA: not mapped as array")]
119 NotMappedAsArray,
120
121 #[error("CUDA: not mapped as pointer")]
123 NotMappedAsPointer,
124
125 #[error("CUDA: uncorrectable ECC error")]
127 EccUncorrectable,
128
129 #[error("CUDA: unsupported limit")]
131 UnsupportedLimit,
132
133 #[error("CUDA: context already in use")]
135 ContextAlreadyInUse,
136
137 #[error("CUDA: peer access unsupported")]
139 PeerAccessUnsupported,
140
141 #[error("CUDA: invalid PTX")]
143 InvalidPtx,
144
145 #[error("CUDA: invalid graphics context")]
147 InvalidGraphicsContext,
148
149 #[error("CUDA: NVLINK uncorrectable error")]
151 NvlinkUncorrectable,
152
153 #[error("CUDA: JIT compiler not found")]
155 JitCompilerNotFound,
156
157 #[error("CUDA: unsupported PTX version")]
159 UnsupportedPtxVersion,
160
161 #[error("CUDA: JIT compilation disabled")]
163 JitCompilationDisabled,
164
165 #[error("CUDA: unsupported exec affinity")]
167 UnsupportedExecAffinity,
168
169 #[error("CUDA: unsupported device-side sync")]
171 UnsupportedDevsideSync,
172
173 #[error("CUDA: invalid source")]
176 InvalidSource,
177
178 #[error("CUDA: file not found")]
180 FileNotFound,
181
182 #[error("CUDA: shared object symbol not found")]
184 SharedObjectSymbolNotFound,
185
186 #[error("CUDA: shared object init failed")]
188 SharedObjectInitFailed,
189
190 #[error("CUDA: operating system error")]
192 OperatingSystem,
193
194 #[error("CUDA: invalid handle")]
197 InvalidHandle,
198
199 #[error("CUDA: illegal state")]
201 IllegalState,
202
203 #[error("CUDA: lossy query")]
205 LossyQuery,
206
207 #[error("CUDA: symbol not found")]
210 NotFound,
211
212 #[error("CUDA: not ready (async operation pending)")]
215 NotReady,
216
217 #[error("CUDA: illegal memory address")]
220 IllegalAddress,
221
222 #[error("CUDA: kernel launch out of resources (registers/shared memory)")]
224 LaunchOutOfResources,
225
226 #[error("CUDA: kernel launch timeout")]
228 LaunchTimeout,
229
230 #[error("CUDA: launch incompatible texturing")]
232 LaunchIncompatibleTexturing,
233
234 #[error("CUDA: peer access already enabled")]
236 PeerAccessAlreadyEnabled,
237
238 #[error("CUDA: peer access not enabled")]
240 PeerAccessNotEnabled,
241
242 #[error("CUDA: primary context active")]
244 PrimaryContextActive,
245
246 #[error("CUDA: context is destroyed")]
248 ContextIsDestroyed,
249
250 #[error("CUDA: device-side assert triggered")]
252 Assert,
253
254 #[error("CUDA: too many peers")]
256 TooManyPeers,
257
258 #[error("CUDA: host memory already registered")]
260 HostMemoryAlreadyRegistered,
261
262 #[error("CUDA: host memory not registered")]
264 HostMemoryNotRegistered,
265
266 #[error("CUDA: hardware stack error")]
268 HardwareStackError,
269
270 #[error("CUDA: illegal instruction")]
272 IllegalInstruction,
273
274 #[error("CUDA: misaligned address")]
276 MisalignedAddress,
277
278 #[error("CUDA: invalid address space")]
280 InvalidAddressSpace,
281
282 #[error("CUDA: invalid program counter")]
284 InvalidPc,
285
286 #[error("CUDA: kernel launch failed")]
288 LaunchFailed,
289
290 #[error("CUDA: cooperative launch too large")]
292 CooperativeLaunchTooLarge,
293
294 #[error("CUDA: not permitted")]
297 NotPermitted,
298
299 #[error("CUDA: not supported")]
301 NotSupported,
302
303 #[error("CUDA: system not ready")]
305 SystemNotReady,
306
307 #[error("CUDA: system driver mismatch")]
309 SystemDriverMismatch,
310
311 #[error("CUDA: compat not supported on device")]
313 CompatNotSupportedOnDevice,
314
315 #[error("CUDA: MPS connection failed")]
317 MpsConnectionFailed,
318
319 #[error("CUDA: MPS RPC failure")]
321 MpsRpcFailure,
322
323 #[error("CUDA: MPS server not ready")]
325 MpsServerNotReady,
326
327 #[error("CUDA: MPS max clients reached")]
329 MpsMaxClientsReached,
330
331 #[error("CUDA: MPS max connections reached")]
333 MpsMaxConnectionsReached,
334
335 #[error("CUDA: MPS client terminated")]
337 MpsClientTerminated,
338
339 #[error("CUDA: CDP not supported")]
341 CdpNotSupported,
342
343 #[error("CUDA: CDP version mismatch")]
345 CdpVersionMismatch,
346
347 #[error("CUDA: stream capture unsupported")]
350 StreamCaptureUnsupported,
351
352 #[error("CUDA: stream capture invalidated")]
354 StreamCaptureInvalidated,
355
356 #[error("CUDA: stream capture merge not permitted")]
358 StreamCaptureMerge,
359
360 #[error("CUDA: stream capture unmatched")]
362 StreamCaptureUnmatched,
363
364 #[error("CUDA: stream capture unjoined")]
366 StreamCaptureUnjoined,
367
368 #[error("CUDA: stream capture isolation violation")]
370 StreamCaptureIsolation,
371
372 #[error("CUDA: implicit stream in graph capture")]
374 StreamCaptureImplicit,
375
376 #[error("CUDA: captured event error")]
378 CapturedEvent,
379
380 #[error("CUDA: stream capture wrong thread")]
382 StreamCaptureWrongThread,
383
384 #[error("CUDA: async operation timed out")]
386 Timeout,
387
388 #[error("CUDA: graph exec update failure")]
390 GraphExecUpdateFailure,
391
392 #[error("CUDA: external device error")]
394 ExternalDevice,
395
396 #[error("CUDA: invalid cluster size")]
398 InvalidClusterSize,
399
400 #[error("CUDA: function not loaded")]
402 FunctionNotLoaded,
403
404 #[error("CUDA: invalid resource type")]
406 InvalidResourceType,
407
408 #[error("CUDA: invalid resource configuration")]
410 InvalidResourceConfiguration,
411
412 #[error("CUDA: unknown error (code {0})")]
415 Unknown(u32),
416}
417
418impl CudaError {
419 #[allow(clippy::too_many_lines)]
424 pub fn from_raw(code: u32) -> Self {
425 match code {
426 ffi::CUDA_ERROR_INVALID_VALUE => Self::InvalidValue,
427 ffi::CUDA_ERROR_OUT_OF_MEMORY => Self::OutOfMemory,
428 ffi::CUDA_ERROR_NOT_INITIALIZED => Self::NotInitialized,
429 ffi::CUDA_ERROR_DEINITIALIZED => Self::Deinitialized,
430 ffi::CUDA_ERROR_PROFILER_DISABLED => Self::ProfilerDisabled,
431 ffi::CUDA_ERROR_PROFILER_NOT_INITIALIZED => Self::ProfilerNotInitialized,
432 ffi::CUDA_ERROR_PROFILER_ALREADY_STARTED => Self::ProfilerAlreadyStarted,
433 ffi::CUDA_ERROR_PROFILER_ALREADY_STOPPED => Self::ProfilerAlreadyStopped,
434 ffi::CUDA_ERROR_STUB_LIBRARY => Self::StubLibrary,
435 ffi::CUDA_ERROR_DEVICE_UNAVAILABLE => Self::DeviceUnavailable,
436 ffi::CUDA_ERROR_NO_DEVICE => Self::NoDevice,
437 ffi::CUDA_ERROR_INVALID_DEVICE => Self::InvalidDevice,
438 ffi::CUDA_ERROR_DEVICE_NOT_LICENSED => Self::DeviceNotLicensed,
439 ffi::CUDA_ERROR_INVALID_IMAGE => Self::InvalidImage,
440 ffi::CUDA_ERROR_INVALID_CONTEXT => Self::InvalidContext,
441 ffi::CUDA_ERROR_CONTEXT_ALREADY_CURRENT => Self::ContextAlreadyCurrent,
442 ffi::CUDA_ERROR_MAP_FAILED => Self::MapFailed,
443 ffi::CUDA_ERROR_UNMAP_FAILED => Self::UnmapFailed,
444 ffi::CUDA_ERROR_ARRAY_IS_MAPPED => Self::ArrayIsMapped,
445 ffi::CUDA_ERROR_ALREADY_MAPPED => Self::AlreadyMapped,
446 ffi::CUDA_ERROR_NO_BINARY_FOR_GPU => Self::NoBinaryForGpu,
447 ffi::CUDA_ERROR_ALREADY_ACQUIRED => Self::AlreadyAcquired,
448 ffi::CUDA_ERROR_NOT_MAPPED => Self::NotMapped,
449 ffi::CUDA_ERROR_NOT_MAPPED_AS_ARRAY => Self::NotMappedAsArray,
450 ffi::CUDA_ERROR_NOT_MAPPED_AS_POINTER => Self::NotMappedAsPointer,
451 ffi::CUDA_ERROR_ECC_UNCORRECTABLE => Self::EccUncorrectable,
452 ffi::CUDA_ERROR_UNSUPPORTED_LIMIT => Self::UnsupportedLimit,
453 ffi::CUDA_ERROR_CONTEXT_ALREADY_IN_USE => Self::ContextAlreadyInUse,
454 ffi::CUDA_ERROR_PEER_ACCESS_UNSUPPORTED => Self::PeerAccessUnsupported,
455 ffi::CUDA_ERROR_INVALID_PTX => Self::InvalidPtx,
456 ffi::CUDA_ERROR_INVALID_GRAPHICS_CONTEXT => Self::InvalidGraphicsContext,
457 ffi::CUDA_ERROR_NVLINK_UNCORRECTABLE => Self::NvlinkUncorrectable,
458 ffi::CUDA_ERROR_JIT_COMPILER_NOT_FOUND => Self::JitCompilerNotFound,
459 ffi::CUDA_ERROR_UNSUPPORTED_PTX_VERSION => Self::UnsupportedPtxVersion,
460 ffi::CUDA_ERROR_JIT_COMPILATION_DISABLED => Self::JitCompilationDisabled,
461 ffi::CUDA_ERROR_UNSUPPORTED_EXEC_AFFINITY => Self::UnsupportedExecAffinity,
462 ffi::CUDA_ERROR_UNSUPPORTED_DEVSIDE_SYNC => Self::UnsupportedDevsideSync,
463 ffi::CUDA_ERROR_INVALID_SOURCE => Self::InvalidSource,
464 ffi::CUDA_ERROR_FILE_NOT_FOUND => Self::FileNotFound,
465 ffi::CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND => Self::SharedObjectSymbolNotFound,
466 ffi::CUDA_ERROR_SHARED_OBJECT_INIT_FAILED => Self::SharedObjectInitFailed,
467 ffi::CUDA_ERROR_OPERATING_SYSTEM => Self::OperatingSystem,
468 ffi::CUDA_ERROR_INVALID_HANDLE => Self::InvalidHandle,
469 ffi::CUDA_ERROR_ILLEGAL_STATE => Self::IllegalState,
470 ffi::CUDA_ERROR_LOSSY_QUERY => Self::LossyQuery,
471 ffi::CUDA_ERROR_NOT_FOUND => Self::NotFound,
472 ffi::CUDA_ERROR_NOT_READY => Self::NotReady,
473 ffi::CUDA_ERROR_ILLEGAL_ADDRESS => Self::IllegalAddress,
474 ffi::CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES => Self::LaunchOutOfResources,
475 ffi::CUDA_ERROR_LAUNCH_TIMEOUT => Self::LaunchTimeout,
476 ffi::CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING => Self::LaunchIncompatibleTexturing,
477 ffi::CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED => Self::PeerAccessAlreadyEnabled,
478 ffi::CUDA_ERROR_PEER_ACCESS_NOT_ENABLED => Self::PeerAccessNotEnabled,
479 ffi::CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE => Self::PrimaryContextActive,
480 ffi::CUDA_ERROR_CONTEXT_IS_DESTROYED => Self::ContextIsDestroyed,
481 ffi::CUDA_ERROR_ASSERT => Self::Assert,
482 ffi::CUDA_ERROR_TOO_MANY_PEERS => Self::TooManyPeers,
483 ffi::CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED => Self::HostMemoryAlreadyRegistered,
484 ffi::CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED => Self::HostMemoryNotRegistered,
485 ffi::CUDA_ERROR_HARDWARE_STACK_ERROR => Self::HardwareStackError,
486 ffi::CUDA_ERROR_ILLEGAL_INSTRUCTION => Self::IllegalInstruction,
487 ffi::CUDA_ERROR_MISALIGNED_ADDRESS => Self::MisalignedAddress,
488 ffi::CUDA_ERROR_INVALID_ADDRESS_SPACE => Self::InvalidAddressSpace,
489 ffi::CUDA_ERROR_INVALID_PC => Self::InvalidPc,
490 ffi::CUDA_ERROR_LAUNCH_FAILED => Self::LaunchFailed,
491 ffi::CUDA_ERROR_COOPERATIVE_LAUNCH_TOO_LARGE => Self::CooperativeLaunchTooLarge,
492 ffi::CUDA_ERROR_NOT_PERMITTED => Self::NotPermitted,
493 ffi::CUDA_ERROR_NOT_SUPPORTED => Self::NotSupported,
494 ffi::CUDA_ERROR_SYSTEM_NOT_READY => Self::SystemNotReady,
495 ffi::CUDA_ERROR_SYSTEM_DRIVER_MISMATCH => Self::SystemDriverMismatch,
496 ffi::CUDA_ERROR_COMPAT_NOT_SUPPORTED_ON_DEVICE => Self::CompatNotSupportedOnDevice,
497 ffi::CUDA_ERROR_MPS_CONNECTION_FAILED => Self::MpsConnectionFailed,
498 ffi::CUDA_ERROR_MPS_RPC_FAILURE => Self::MpsRpcFailure,
499 ffi::CUDA_ERROR_MPS_SERVER_NOT_READY => Self::MpsServerNotReady,
500 ffi::CUDA_ERROR_MPS_MAX_CLIENTS_REACHED => Self::MpsMaxClientsReached,
501 ffi::CUDA_ERROR_MPS_MAX_CONNECTIONS_REACHED => Self::MpsMaxConnectionsReached,
502 ffi::CUDA_ERROR_MPS_CLIENT_TERMINATED => Self::MpsClientTerminated,
503 ffi::CUDA_ERROR_CDP_NOT_SUPPORTED => Self::CdpNotSupported,
504 ffi::CUDA_ERROR_CDP_VERSION_MISMATCH => Self::CdpVersionMismatch,
505 ffi::CUDA_ERROR_STREAM_CAPTURE_UNSUPPORTED => Self::StreamCaptureUnsupported,
506 ffi::CUDA_ERROR_STREAM_CAPTURE_INVALIDATED => Self::StreamCaptureInvalidated,
507 ffi::CUDA_ERROR_STREAM_CAPTURE_MERGE => Self::StreamCaptureMerge,
508 ffi::CUDA_ERROR_STREAM_CAPTURE_UNMATCHED => Self::StreamCaptureUnmatched,
509 ffi::CUDA_ERROR_STREAM_CAPTURE_UNJOINED => Self::StreamCaptureUnjoined,
510 ffi::CUDA_ERROR_STREAM_CAPTURE_ISOLATION => Self::StreamCaptureIsolation,
511 ffi::CUDA_ERROR_STREAM_CAPTURE_IMPLICIT => Self::StreamCaptureImplicit,
512 ffi::CUDA_ERROR_CAPTURED_EVENT => Self::CapturedEvent,
513 ffi::CUDA_ERROR_STREAM_CAPTURE_WRONG_THREAD => Self::StreamCaptureWrongThread,
514 ffi::CUDA_ERROR_TIMEOUT => Self::Timeout,
515 ffi::CUDA_ERROR_GRAPH_EXEC_UPDATE_FAILURE => Self::GraphExecUpdateFailure,
516 ffi::CUDA_ERROR_EXTERNAL_DEVICE => Self::ExternalDevice,
517 ffi::CUDA_ERROR_INVALID_CLUSTER_SIZE => Self::InvalidClusterSize,
518 ffi::CUDA_ERROR_FUNCTION_NOT_LOADED => Self::FunctionNotLoaded,
519 ffi::CUDA_ERROR_INVALID_RESOURCE_TYPE => Self::InvalidResourceType,
520 ffi::CUDA_ERROR_INVALID_RESOURCE_CONFIGURATION => Self::InvalidResourceConfiguration,
521 ffi::CUDA_ERROR_UNKNOWN => Self::Unknown(999),
522 other => Self::Unknown(other),
523 }
524 }
525
526 #[must_use]
553 pub fn is_fatal(&self) -> bool {
554 matches!(
555 self,
556 Self::IllegalAddress
558 | Self::LaunchFailed
559 | Self::HardwareStackError
560 | Self::IllegalInstruction
561 | Self::MisalignedAddress
562 | Self::InvalidAddressSpace
563 | Self::InvalidPc
564 | Self::Assert
565 | Self::EccUncorrectable
566 | Self::NvlinkUncorrectable
567 | Self::ContextIsDestroyed
569 | Self::Deinitialized
570 )
571 }
572
573 #[must_use]
587 pub fn is_usage_error(&self) -> bool {
588 matches!(
589 self,
590 Self::InvalidValue
591 | Self::InvalidDevice
592 | Self::InvalidContext
593 | Self::InvalidHandle
594 | Self::InvalidImage
595 | Self::InvalidPtx
596 | Self::InvalidSource
597 | Self::InvalidClusterSize
598 | Self::NoDevice
599 | Self::UnsupportedLimit
600 | Self::NotSupported
601 | Self::NotPermitted
602 )
603 }
604
605 #[allow(clippy::too_many_lines)]
607 pub fn as_raw(&self) -> u32 {
608 match self {
609 Self::InvalidValue => ffi::CUDA_ERROR_INVALID_VALUE,
610 Self::OutOfMemory => ffi::CUDA_ERROR_OUT_OF_MEMORY,
611 Self::NotInitialized => ffi::CUDA_ERROR_NOT_INITIALIZED,
612 Self::Deinitialized => ffi::CUDA_ERROR_DEINITIALIZED,
613 Self::ProfilerDisabled => ffi::CUDA_ERROR_PROFILER_DISABLED,
614 Self::ProfilerNotInitialized => ffi::CUDA_ERROR_PROFILER_NOT_INITIALIZED,
615 Self::ProfilerAlreadyStarted => ffi::CUDA_ERROR_PROFILER_ALREADY_STARTED,
616 Self::ProfilerAlreadyStopped => ffi::CUDA_ERROR_PROFILER_ALREADY_STOPPED,
617 Self::StubLibrary => ffi::CUDA_ERROR_STUB_LIBRARY,
618 Self::DeviceUnavailable => ffi::CUDA_ERROR_DEVICE_UNAVAILABLE,
619 Self::NoDevice => ffi::CUDA_ERROR_NO_DEVICE,
620 Self::InvalidDevice => ffi::CUDA_ERROR_INVALID_DEVICE,
621 Self::DeviceNotLicensed => ffi::CUDA_ERROR_DEVICE_NOT_LICENSED,
622 Self::InvalidImage => ffi::CUDA_ERROR_INVALID_IMAGE,
623 Self::InvalidContext => ffi::CUDA_ERROR_INVALID_CONTEXT,
624 Self::ContextAlreadyCurrent => ffi::CUDA_ERROR_CONTEXT_ALREADY_CURRENT,
625 Self::MapFailed => ffi::CUDA_ERROR_MAP_FAILED,
626 Self::UnmapFailed => ffi::CUDA_ERROR_UNMAP_FAILED,
627 Self::ArrayIsMapped => ffi::CUDA_ERROR_ARRAY_IS_MAPPED,
628 Self::AlreadyMapped => ffi::CUDA_ERROR_ALREADY_MAPPED,
629 Self::NoBinaryForGpu => ffi::CUDA_ERROR_NO_BINARY_FOR_GPU,
630 Self::AlreadyAcquired => ffi::CUDA_ERROR_ALREADY_ACQUIRED,
631 Self::NotMapped => ffi::CUDA_ERROR_NOT_MAPPED,
632 Self::NotMappedAsArray => ffi::CUDA_ERROR_NOT_MAPPED_AS_ARRAY,
633 Self::NotMappedAsPointer => ffi::CUDA_ERROR_NOT_MAPPED_AS_POINTER,
634 Self::EccUncorrectable => ffi::CUDA_ERROR_ECC_UNCORRECTABLE,
635 Self::UnsupportedLimit => ffi::CUDA_ERROR_UNSUPPORTED_LIMIT,
636 Self::ContextAlreadyInUse => ffi::CUDA_ERROR_CONTEXT_ALREADY_IN_USE,
637 Self::PeerAccessUnsupported => ffi::CUDA_ERROR_PEER_ACCESS_UNSUPPORTED,
638 Self::InvalidPtx => ffi::CUDA_ERROR_INVALID_PTX,
639 Self::InvalidGraphicsContext => ffi::CUDA_ERROR_INVALID_GRAPHICS_CONTEXT,
640 Self::NvlinkUncorrectable => ffi::CUDA_ERROR_NVLINK_UNCORRECTABLE,
641 Self::JitCompilerNotFound => ffi::CUDA_ERROR_JIT_COMPILER_NOT_FOUND,
642 Self::UnsupportedPtxVersion => ffi::CUDA_ERROR_UNSUPPORTED_PTX_VERSION,
643 Self::JitCompilationDisabled => ffi::CUDA_ERROR_JIT_COMPILATION_DISABLED,
644 Self::UnsupportedExecAffinity => ffi::CUDA_ERROR_UNSUPPORTED_EXEC_AFFINITY,
645 Self::UnsupportedDevsideSync => ffi::CUDA_ERROR_UNSUPPORTED_DEVSIDE_SYNC,
646 Self::InvalidSource => ffi::CUDA_ERROR_INVALID_SOURCE,
647 Self::FileNotFound => ffi::CUDA_ERROR_FILE_NOT_FOUND,
648 Self::SharedObjectSymbolNotFound => ffi::CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND,
649 Self::SharedObjectInitFailed => ffi::CUDA_ERROR_SHARED_OBJECT_INIT_FAILED,
650 Self::OperatingSystem => ffi::CUDA_ERROR_OPERATING_SYSTEM,
651 Self::InvalidHandle => ffi::CUDA_ERROR_INVALID_HANDLE,
652 Self::IllegalState => ffi::CUDA_ERROR_ILLEGAL_STATE,
653 Self::LossyQuery => ffi::CUDA_ERROR_LOSSY_QUERY,
654 Self::NotFound => ffi::CUDA_ERROR_NOT_FOUND,
655 Self::NotReady => ffi::CUDA_ERROR_NOT_READY,
656 Self::IllegalAddress => ffi::CUDA_ERROR_ILLEGAL_ADDRESS,
657 Self::LaunchOutOfResources => ffi::CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES,
658 Self::LaunchTimeout => ffi::CUDA_ERROR_LAUNCH_TIMEOUT,
659 Self::LaunchIncompatibleTexturing => ffi::CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING,
660 Self::PeerAccessAlreadyEnabled => ffi::CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED,
661 Self::PeerAccessNotEnabled => ffi::CUDA_ERROR_PEER_ACCESS_NOT_ENABLED,
662 Self::PrimaryContextActive => ffi::CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE,
663 Self::ContextIsDestroyed => ffi::CUDA_ERROR_CONTEXT_IS_DESTROYED,
664 Self::Assert => ffi::CUDA_ERROR_ASSERT,
665 Self::TooManyPeers => ffi::CUDA_ERROR_TOO_MANY_PEERS,
666 Self::HostMemoryAlreadyRegistered => ffi::CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED,
667 Self::HostMemoryNotRegistered => ffi::CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED,
668 Self::HardwareStackError => ffi::CUDA_ERROR_HARDWARE_STACK_ERROR,
669 Self::IllegalInstruction => ffi::CUDA_ERROR_ILLEGAL_INSTRUCTION,
670 Self::MisalignedAddress => ffi::CUDA_ERROR_MISALIGNED_ADDRESS,
671 Self::InvalidAddressSpace => ffi::CUDA_ERROR_INVALID_ADDRESS_SPACE,
672 Self::InvalidPc => ffi::CUDA_ERROR_INVALID_PC,
673 Self::LaunchFailed => ffi::CUDA_ERROR_LAUNCH_FAILED,
674 Self::CooperativeLaunchTooLarge => ffi::CUDA_ERROR_COOPERATIVE_LAUNCH_TOO_LARGE,
675 Self::NotPermitted => ffi::CUDA_ERROR_NOT_PERMITTED,
676 Self::NotSupported => ffi::CUDA_ERROR_NOT_SUPPORTED,
677 Self::SystemNotReady => ffi::CUDA_ERROR_SYSTEM_NOT_READY,
678 Self::SystemDriverMismatch => ffi::CUDA_ERROR_SYSTEM_DRIVER_MISMATCH,
679 Self::CompatNotSupportedOnDevice => ffi::CUDA_ERROR_COMPAT_NOT_SUPPORTED_ON_DEVICE,
680 Self::MpsConnectionFailed => ffi::CUDA_ERROR_MPS_CONNECTION_FAILED,
681 Self::MpsRpcFailure => ffi::CUDA_ERROR_MPS_RPC_FAILURE,
682 Self::MpsServerNotReady => ffi::CUDA_ERROR_MPS_SERVER_NOT_READY,
683 Self::MpsMaxClientsReached => ffi::CUDA_ERROR_MPS_MAX_CLIENTS_REACHED,
684 Self::MpsMaxConnectionsReached => ffi::CUDA_ERROR_MPS_MAX_CONNECTIONS_REACHED,
685 Self::MpsClientTerminated => ffi::CUDA_ERROR_MPS_CLIENT_TERMINATED,
686 Self::CdpNotSupported => ffi::CUDA_ERROR_CDP_NOT_SUPPORTED,
687 Self::CdpVersionMismatch => ffi::CUDA_ERROR_CDP_VERSION_MISMATCH,
688 Self::StreamCaptureUnsupported => ffi::CUDA_ERROR_STREAM_CAPTURE_UNSUPPORTED,
689 Self::StreamCaptureInvalidated => ffi::CUDA_ERROR_STREAM_CAPTURE_INVALIDATED,
690 Self::StreamCaptureMerge => ffi::CUDA_ERROR_STREAM_CAPTURE_MERGE,
691 Self::StreamCaptureUnmatched => ffi::CUDA_ERROR_STREAM_CAPTURE_UNMATCHED,
692 Self::StreamCaptureUnjoined => ffi::CUDA_ERROR_STREAM_CAPTURE_UNJOINED,
693 Self::StreamCaptureIsolation => ffi::CUDA_ERROR_STREAM_CAPTURE_ISOLATION,
694 Self::StreamCaptureImplicit => ffi::CUDA_ERROR_STREAM_CAPTURE_IMPLICIT,
695 Self::CapturedEvent => ffi::CUDA_ERROR_CAPTURED_EVENT,
696 Self::StreamCaptureWrongThread => ffi::CUDA_ERROR_STREAM_CAPTURE_WRONG_THREAD,
697 Self::Timeout => ffi::CUDA_ERROR_TIMEOUT,
698 Self::GraphExecUpdateFailure => ffi::CUDA_ERROR_GRAPH_EXEC_UPDATE_FAILURE,
699 Self::ExternalDevice => ffi::CUDA_ERROR_EXTERNAL_DEVICE,
700 Self::InvalidClusterSize => ffi::CUDA_ERROR_INVALID_CLUSTER_SIZE,
701 Self::FunctionNotLoaded => ffi::CUDA_ERROR_FUNCTION_NOT_LOADED,
702 Self::InvalidResourceType => ffi::CUDA_ERROR_INVALID_RESOURCE_TYPE,
703 Self::InvalidResourceConfiguration => ffi::CUDA_ERROR_INVALID_RESOURCE_CONFIGURATION,
704 Self::Unknown(code) => *code,
705 }
706 }
707}
708
709pub type CudaResult<T> = Result<T, CudaError>;
715
716#[inline(always)]
725pub fn check(result: u32) -> CudaResult<()> {
726 if result == 0 {
727 Ok(())
728 } else {
729 Err(CudaError::from_raw(result))
730 }
731}
732
733#[macro_export]
748macro_rules! cuda_call {
749 ($expr:expr) => {
750 $crate::error::check(unsafe { $expr })
751 };
752}
753
754#[derive(Debug, thiserror::Error)]
760pub enum DriverLoadError {
761 #[error("CUDA driver library not found (tried: {candidates:?}): {last_error}")]
763 LibraryNotFound {
764 candidates: Vec<String>,
766 last_error: String,
768 },
769
770 #[error("failed to load symbol '{symbol}': {reason}")]
772 SymbolNotFound {
773 symbol: &'static str,
775 reason: String,
777 },
778
779 #[error("cuInit(0) failed with CUDA error code {code}")]
786 InitializationFailed {
787 code: u32,
789 },
790
791 #[error("CUDA driver not supported on this platform")]
793 UnsupportedPlatform,
794}
795
796#[cfg(test)]
801mod tests {
802 use super::*;
803
804 #[test]
805 fn test_check_success() {
806 assert!(check(0).is_ok());
807 }
808
809 #[test]
810 fn test_check_error() {
811 let result = check(1);
812 assert!(result.is_err());
813 assert_eq!(result.err(), Some(CudaError::InvalidValue));
814 }
815
816 #[test]
817 fn test_check_out_of_memory() {
818 let result = check(2);
819 assert_eq!(result.err(), Some(CudaError::OutOfMemory));
820 }
821
822 #[test]
823 fn test_check_not_initialized() {
824 let result = check(3);
825 assert_eq!(result.err(), Some(CudaError::NotInitialized));
826 }
827
828 #[test]
829 fn test_from_raw_roundtrip() {
830 let codes: &[u32] = &[
832 1, 2, 3, 4, 5, 6, 7, 8, 34, 46, 100, 101, 102, 200, 201, 202, 205, 206, 207, 208, 209,
833 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 300,
834 301, 302, 303, 304, 400, 401, 402, 500, 600, 700, 701, 702, 703, 704, 705, 708, 709,
835 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 800, 801, 802, 803, 804, 805,
836 806, 807, 808, 809, 810, 811, 812, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909,
837 910, 911, 912, 913, 914, 915, 999,
838 ];
839 for &code in codes {
840 let err = CudaError::from_raw(code);
841 assert_eq!(
842 err.as_raw(),
843 code,
844 "round-trip failed for code {code}: got {:?}",
845 err
846 );
847 }
848 }
849
850 #[test]
851 fn test_unknown_code() {
852 let err = CudaError::from_raw(12345);
853 assert_eq!(err, CudaError::Unknown(12345));
854 assert_eq!(err.as_raw(), 12345);
855 }
856
857 #[test]
858 fn test_unknown_code_display() {
859 let err = CudaError::from_raw(12345);
860 let msg = format!("{err}");
861 assert!(
862 msg.contains("12345"),
863 "display should contain the code: {msg}"
864 );
865 }
866
867 #[test]
868 fn test_error_display_messages() {
869 assert_eq!(
870 format!("{}", CudaError::InvalidValue),
871 "CUDA: invalid value"
872 );
873 assert_eq!(
874 format!("{}", CudaError::OutOfMemory),
875 "CUDA: out of device memory"
876 );
877 assert_eq!(
878 format!("{}", CudaError::LaunchFailed),
879 "CUDA: kernel launch failed"
880 );
881 assert_eq!(
882 format!("{}", CudaError::NotReady),
883 "CUDA: not ready (async operation pending)"
884 );
885 }
886
887 #[test]
888 fn test_error_is_copy() {
889 let err = CudaError::InvalidValue;
890 let copy = err;
891 assert_eq!(err, copy);
892 }
893
894 #[test]
895 fn test_error_implements_std_error() {
896 fn assert_error<T: std::error::Error>() {}
897 assert_error::<CudaError>();
898 assert_error::<DriverLoadError>();
899 }
900
901 #[test]
902 fn test_driver_load_error_display() {
903 let err = DriverLoadError::LibraryNotFound {
904 candidates: vec!["libcuda.so".to_string()],
905 last_error: "no such file or directory".to_string(),
906 };
907 let msg = format!("{err}");
908 assert!(msg.contains("libcuda.so"));
909
910 let err = DriverLoadError::SymbolNotFound {
911 symbol: "cuInit",
912 reason: "not found".to_string(),
913 };
914 let msg = format!("{err}");
915 assert!(msg.contains("cuInit"));
916
917 let err = DriverLoadError::UnsupportedPlatform;
918 let msg = format!("{err}");
919 assert!(msg.contains("not supported"));
920 }
921
922 #[test]
923 fn test_cuda_call_macro() {
924 unsafe fn fake_success() -> u32 {
926 0
927 }
928 unsafe fn fake_launch_failed() -> u32 {
929 719
930 }
931
932 let result = cuda_call!(fake_success());
933 assert!(result.is_ok());
934
935 let result = cuda_call!(fake_launch_failed());
936 assert_eq!(result.err(), Some(CudaError::LaunchFailed));
937 }
938
939 #[test]
940 fn test_error_hash() {
941 use std::collections::HashSet;
942 let mut set = HashSet::new();
943 set.insert(CudaError::InvalidValue);
944 set.insert(CudaError::OutOfMemory);
945 set.insert(CudaError::InvalidValue); assert_eq!(set.len(), 2);
947 }
948
949 #[test]
950 fn test_cuda_result_type_alias() {
951 fn returns_ok() -> CudaResult<i32> {
952 Ok(42)
953 }
954 fn returns_err() -> CudaResult<i32> {
955 Err(CudaError::NoDevice)
956 }
957 assert_eq!(returns_ok().ok(), Some(42));
958 assert_eq!(returns_err().err(), Some(CudaError::NoDevice));
959 }
960
961 #[test]
967 fn test_all_common_cuda_error_variants_have_display() {
968 let errors: &[CudaError] = &[
969 CudaError::InvalidValue,
971 CudaError::OutOfMemory,
972 CudaError::NotInitialized,
973 CudaError::Deinitialized,
974 CudaError::ProfilerDisabled,
975 CudaError::ProfilerNotInitialized,
976 CudaError::ProfilerAlreadyStarted,
977 CudaError::ProfilerAlreadyStopped,
978 CudaError::StubLibrary,
980 CudaError::DeviceUnavailable,
981 CudaError::NoDevice,
983 CudaError::InvalidDevice,
984 CudaError::DeviceNotLicensed,
985 CudaError::InvalidImage,
987 CudaError::InvalidContext,
988 CudaError::ContextAlreadyCurrent,
989 CudaError::MapFailed,
990 CudaError::UnmapFailed,
991 CudaError::EccUncorrectable,
992 CudaError::InvalidSource,
994 CudaError::FileNotFound,
995 CudaError::SharedObjectSymbolNotFound,
996 CudaError::InvalidHandle,
998 CudaError::IllegalState,
999 CudaError::NotFound,
1000 CudaError::NotReady,
1002 CudaError::IllegalAddress,
1004 CudaError::LaunchOutOfResources,
1005 CudaError::LaunchTimeout,
1006 CudaError::LaunchFailed,
1007 CudaError::CooperativeLaunchTooLarge,
1008 CudaError::NotPermitted,
1010 CudaError::NotSupported,
1011 CudaError::HardwareStackError,
1013 CudaError::IllegalInstruction,
1014 CudaError::MisalignedAddress,
1015 CudaError::InvalidAddressSpace,
1016 CudaError::InvalidPc,
1017 CudaError::PeerAccessAlreadyEnabled,
1019 CudaError::PeerAccessNotEnabled,
1020 CudaError::ContextIsDestroyed,
1021 CudaError::StreamCaptureUnsupported,
1023 CudaError::StreamCaptureInvalidated,
1024 CudaError::InvalidClusterSize,
1025 CudaError::FunctionNotLoaded,
1026 CudaError::Unknown(99999),
1028 ];
1029 for err in errors {
1030 let display = format!("{err}");
1031 assert!(
1032 !display.is_empty(),
1033 "CudaError::{err:?} has an empty Display string"
1034 );
1035 }
1036 }
1037
1038 #[test]
1040 fn test_cuda_error_from_result_code() {
1041 let pairs: &[(u32, CudaError)] = &[
1042 (1, CudaError::InvalidValue),
1043 (2, CudaError::OutOfMemory),
1044 (3, CudaError::NotInitialized),
1045 (4, CudaError::Deinitialized),
1046 (100, CudaError::NoDevice),
1047 (101, CudaError::InvalidDevice),
1048 (200, CudaError::InvalidImage),
1049 (201, CudaError::InvalidContext),
1050 (400, CudaError::InvalidHandle),
1051 (500, CudaError::NotFound),
1052 (600, CudaError::NotReady),
1053 (700, CudaError::IllegalAddress),
1054 (701, CudaError::LaunchOutOfResources),
1055 (702, CudaError::LaunchTimeout),
1056 (719, CudaError::LaunchFailed),
1057 (800, CudaError::NotPermitted),
1058 (801, CudaError::NotSupported),
1059 (912, CudaError::InvalidClusterSize),
1060 (999, CudaError::Unknown(999)),
1061 ];
1062 for &(code, ref expected) in pairs {
1063 let got = CudaError::from_raw(code);
1064 assert_eq!(
1065 &got, expected,
1066 "from_raw({code}) should be {expected:?}, got {got:?}"
1067 );
1068 assert_eq!(
1069 got.as_raw(),
1070 code,
1071 "as_raw() round-trip failed for code {code}"
1072 );
1073 }
1074 }
1075
1076 #[test]
1078 fn test_cuda_error_is_fatal() {
1079 let fatal: &[CudaError] = &[
1081 CudaError::IllegalAddress,
1082 CudaError::LaunchFailed,
1083 CudaError::HardwareStackError,
1084 CudaError::IllegalInstruction,
1085 CudaError::MisalignedAddress,
1086 CudaError::InvalidAddressSpace,
1087 CudaError::InvalidPc,
1088 CudaError::Assert,
1089 CudaError::EccUncorrectable,
1090 CudaError::NvlinkUncorrectable,
1091 CudaError::ContextIsDestroyed,
1092 CudaError::Deinitialized,
1093 ];
1094 for err in fatal {
1095 assert!(
1096 err.is_fatal(),
1097 "CudaError::{err:?} should be classified as fatal"
1098 );
1099 }
1100
1101 let non_fatal: &[CudaError] = &[
1103 CudaError::InvalidValue,
1104 CudaError::OutOfMemory,
1105 CudaError::NotInitialized,
1106 CudaError::NoDevice,
1107 CudaError::NotReady,
1108 CudaError::LaunchOutOfResources,
1109 CudaError::LaunchTimeout,
1110 CudaError::NotPermitted,
1111 CudaError::NotSupported,
1112 CudaError::InvalidClusterSize,
1113 CudaError::Unknown(99),
1114 ];
1115 for err in non_fatal {
1116 assert!(
1117 !err.is_fatal(),
1118 "CudaError::{err:?} should NOT be classified as fatal"
1119 );
1120 }
1121 }
1122
1123 #[test]
1125 fn test_cuda_error_is_usage_error() {
1126 let usage: &[CudaError] = &[
1127 CudaError::InvalidValue,
1128 CudaError::InvalidDevice,
1129 CudaError::InvalidContext,
1130 CudaError::InvalidHandle,
1131 CudaError::NoDevice,
1132 ];
1133 for err in usage {
1134 assert!(
1135 err.is_usage_error(),
1136 "CudaError::{err:?} should be a usage error"
1137 );
1138 }
1139
1140 let non_usage: &[CudaError] = &[
1141 CudaError::OutOfMemory,
1142 CudaError::LaunchFailed,
1143 CudaError::IllegalAddress,
1144 CudaError::NotReady,
1145 ];
1146 for err in non_usage {
1147 assert!(
1148 !err.is_usage_error(),
1149 "CudaError::{err:?} should NOT be a usage error"
1150 );
1151 }
1152 }
1153
1154 #[test]
1156 fn test_fatal_and_usage_error_are_disjoint() {
1157 let all_errors: &[CudaError] = &[
1159 CudaError::InvalidValue,
1160 CudaError::OutOfMemory,
1161 CudaError::LaunchFailed,
1162 CudaError::IllegalAddress,
1163 CudaError::HardwareStackError,
1164 CudaError::NotReady,
1165 CudaError::InvalidDevice,
1166 ];
1167 for err in all_errors {
1168 assert!(
1169 !(err.is_fatal() && err.is_usage_error()),
1170 "CudaError::{err:?} cannot be both fatal and a usage error"
1171 );
1172 }
1173 }
1174
1175 #[test]
1178 fn test_error_injection_simulation() {
1179 let injected = check(700);
1181 let err = injected.expect_err("error code 700 must be an Err");
1182 assert_eq!(err, CudaError::IllegalAddress);
1183 assert!(err.is_fatal(), "IllegalAddress must be fatal");
1184 assert!(!err.is_usage_error());
1185
1186 let injected = check(1);
1188 let err = injected.expect_err("error code 1 must be an Err");
1189 assert_eq!(err, CudaError::InvalidValue);
1190 assert!(!err.is_fatal(), "InvalidValue must not be fatal");
1191 assert!(err.is_usage_error());
1192
1193 let injected = check(55555);
1195 let err = injected.expect_err("unknown code must be an Err");
1196 assert!(matches!(err, CudaError::Unknown(55555)));
1197 assert!(!err.is_fatal());
1198 assert!(!err.is_usage_error());
1199 }
1200}