1use crate::ffi;
9use crate::module::JitLog;
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)]
25pub enum CudaError {
26 #[error("CUDA: invalid value")]
29 InvalidValue,
30
31 #[error("CUDA: out of device memory")]
33 OutOfMemory,
34
35 #[error("CUDA: not initialized")]
37 NotInitialized,
38
39 #[error("CUDA: deinitialized")]
41 Deinitialized,
42
43 #[error("CUDA: profiler disabled")]
45 ProfilerDisabled,
46
47 #[error("CUDA: profiler not initialized (deprecated)")]
49 ProfilerNotInitialized,
50
51 #[error("CUDA: profiler already started (deprecated)")]
53 ProfilerAlreadyStarted,
54
55 #[error("CUDA: profiler already stopped (deprecated)")]
57 ProfilerAlreadyStopped,
58
59 #[error("CUDA: stub library loaded instead of real driver")]
62 StubLibrary,
63
64 #[error("CUDA: device unavailable")]
66 DeviceUnavailable,
67
68 #[error("CUDA: no device found")]
71 NoDevice,
72
73 #[error("CUDA: invalid device")]
75 InvalidDevice,
76
77 #[error("CUDA: device not licensed")]
79 DeviceNotLicensed,
80
81 #[error("CUDA: invalid PTX/cubin image")]
84 InvalidImage,
85
86 #[error("CUDA: invalid context")]
88 InvalidContext,
89
90 #[error("CUDA: context already current (deprecated)")]
92 ContextAlreadyCurrent,
93
94 #[error("CUDA: map failed")]
96 MapFailed,
97
98 #[error("CUDA: unmap failed")]
100 UnmapFailed,
101
102 #[error("CUDA: array is mapped")]
104 ArrayIsMapped,
105
106 #[error("CUDA: already mapped")]
108 AlreadyMapped,
109
110 #[error("CUDA: no binary for GPU")]
112 NoBinaryForGpu,
113
114 #[error("CUDA: already acquired")]
116 AlreadyAcquired,
117
118 #[error("CUDA: not mapped")]
120 NotMapped,
121
122 #[error("CUDA: not mapped as array")]
124 NotMappedAsArray,
125
126 #[error("CUDA: not mapped as pointer")]
128 NotMappedAsPointer,
129
130 #[error("CUDA: uncorrectable ECC error")]
132 EccUncorrectable,
133
134 #[error("CUDA: unsupported limit")]
136 UnsupportedLimit,
137
138 #[error("CUDA: context already in use")]
140 ContextAlreadyInUse,
141
142 #[error("CUDA: peer access unsupported")]
144 PeerAccessUnsupported,
145
146 #[error("CUDA: invalid PTX")]
148 InvalidPtx,
149
150 #[error("CUDA: invalid graphics context")]
152 InvalidGraphicsContext,
153
154 #[error("CUDA: NVLINK uncorrectable error")]
156 NvlinkUncorrectable,
157
158 #[error("CUDA: JIT compiler not found")]
160 JitCompilerNotFound,
161
162 #[error("CUDA: unsupported PTX version")]
164 UnsupportedPtxVersion,
165
166 #[error("CUDA: JIT compilation disabled")]
168 JitCompilationDisabled,
169
170 #[error("CUDA: unsupported exec affinity")]
172 UnsupportedExecAffinity,
173
174 #[error("CUDA: unsupported device-side sync")]
176 UnsupportedDevsideSync,
177
178 #[error("CUDA: invalid source")]
181 InvalidSource,
182
183 #[error("CUDA: file not found")]
185 FileNotFound,
186
187 #[error("CUDA: shared object symbol not found")]
189 SharedObjectSymbolNotFound,
190
191 #[error("CUDA: shared object init failed")]
193 SharedObjectInitFailed,
194
195 #[error("CUDA: operating system error")]
197 OperatingSystem,
198
199 #[error("CUDA: invalid handle")]
202 InvalidHandle,
203
204 #[error("CUDA: illegal state")]
206 IllegalState,
207
208 #[error("CUDA: lossy query")]
210 LossyQuery,
211
212 #[error("CUDA: symbol not found")]
215 NotFound,
216
217 #[error("CUDA: not ready (async operation pending)")]
220 NotReady,
221
222 #[error("CUDA: illegal memory address")]
225 IllegalAddress,
226
227 #[error("CUDA: kernel launch out of resources (registers/shared memory)")]
229 LaunchOutOfResources,
230
231 #[error("CUDA: kernel launch timeout")]
233 LaunchTimeout,
234
235 #[error("CUDA: launch incompatible texturing")]
237 LaunchIncompatibleTexturing,
238
239 #[error("CUDA: peer access already enabled")]
241 PeerAccessAlreadyEnabled,
242
243 #[error("CUDA: peer access not enabled")]
245 PeerAccessNotEnabled,
246
247 #[error("CUDA: primary context active")]
249 PrimaryContextActive,
250
251 #[error("CUDA: context is destroyed")]
253 ContextIsDestroyed,
254
255 #[error("CUDA: device-side assert triggered")]
257 Assert,
258
259 #[error("CUDA: too many peers")]
261 TooManyPeers,
262
263 #[error("CUDA: host memory already registered")]
265 HostMemoryAlreadyRegistered,
266
267 #[error("CUDA: host memory not registered")]
269 HostMemoryNotRegistered,
270
271 #[error("CUDA: hardware stack error")]
273 HardwareStackError,
274
275 #[error("CUDA: illegal instruction")]
277 IllegalInstruction,
278
279 #[error("CUDA: misaligned address")]
281 MisalignedAddress,
282
283 #[error("CUDA: invalid address space")]
285 InvalidAddressSpace,
286
287 #[error("CUDA: invalid program counter")]
289 InvalidPc,
290
291 #[error("CUDA: kernel launch failed")]
293 LaunchFailed,
294
295 #[error("CUDA: cooperative launch too large")]
297 CooperativeLaunchTooLarge,
298
299 #[error("CUDA: not permitted")]
302 NotPermitted,
303
304 #[error("CUDA: not supported")]
306 NotSupported,
307
308 #[error("CUDA: system not ready")]
310 SystemNotReady,
311
312 #[error("CUDA: system driver mismatch")]
314 SystemDriverMismatch,
315
316 #[error("CUDA: compat not supported on device")]
318 CompatNotSupportedOnDevice,
319
320 #[error("CUDA: MPS connection failed")]
322 MpsConnectionFailed,
323
324 #[error("CUDA: MPS RPC failure")]
326 MpsRpcFailure,
327
328 #[error("CUDA: MPS server not ready")]
330 MpsServerNotReady,
331
332 #[error("CUDA: MPS max clients reached")]
334 MpsMaxClientsReached,
335
336 #[error("CUDA: MPS max connections reached")]
338 MpsMaxConnectionsReached,
339
340 #[error("CUDA: MPS client terminated")]
342 MpsClientTerminated,
343
344 #[error("CUDA: CDP not supported")]
346 CdpNotSupported,
347
348 #[error("CUDA: CDP version mismatch")]
350 CdpVersionMismatch,
351
352 #[error("CUDA: stream capture unsupported")]
355 StreamCaptureUnsupported,
356
357 #[error("CUDA: stream capture invalidated")]
359 StreamCaptureInvalidated,
360
361 #[error("CUDA: stream capture merge not permitted")]
363 StreamCaptureMerge,
364
365 #[error("CUDA: stream capture unmatched")]
367 StreamCaptureUnmatched,
368
369 #[error("CUDA: stream capture unjoined")]
371 StreamCaptureUnjoined,
372
373 #[error("CUDA: stream capture isolation violation")]
375 StreamCaptureIsolation,
376
377 #[error("CUDA: implicit stream in graph capture")]
379 StreamCaptureImplicit,
380
381 #[error("CUDA: captured event error")]
383 CapturedEvent,
384
385 #[error("CUDA: stream capture wrong thread")]
387 StreamCaptureWrongThread,
388
389 #[error("CUDA: async operation timed out")]
391 Timeout,
392
393 #[error("CUDA: graph exec update failure")]
395 GraphExecUpdateFailure,
396
397 #[error("CUDA: external device error")]
399 ExternalDevice,
400
401 #[error("CUDA: invalid cluster size")]
403 InvalidClusterSize,
404
405 #[error("CUDA: function not loaded")]
407 FunctionNotLoaded,
408
409 #[error("CUDA: invalid resource type")]
411 InvalidResourceType,
412
413 #[error("CUDA: invalid resource configuration")]
415 InvalidResourceConfiguration,
416
417 #[error("JIT compilation failed: {diagnostic_count} diagnostic(s); see attached log")]
428 JitFailed {
429 log: Box<JitLog>,
431 diagnostic_count: usize,
434 #[source]
436 source: Box<CudaError>,
437 },
438
439 #[error("CUDA: unknown error (code {0})")]
442 Unknown(u32),
443}
444
445impl CudaError {
446 #[allow(clippy::too_many_lines)]
451 pub fn from_raw(code: u32) -> Self {
452 match code {
453 ffi::CUDA_ERROR_INVALID_VALUE => Self::InvalidValue,
454 ffi::CUDA_ERROR_OUT_OF_MEMORY => Self::OutOfMemory,
455 ffi::CUDA_ERROR_NOT_INITIALIZED => Self::NotInitialized,
456 ffi::CUDA_ERROR_DEINITIALIZED => Self::Deinitialized,
457 ffi::CUDA_ERROR_PROFILER_DISABLED => Self::ProfilerDisabled,
458 ffi::CUDA_ERROR_PROFILER_NOT_INITIALIZED => Self::ProfilerNotInitialized,
459 ffi::CUDA_ERROR_PROFILER_ALREADY_STARTED => Self::ProfilerAlreadyStarted,
460 ffi::CUDA_ERROR_PROFILER_ALREADY_STOPPED => Self::ProfilerAlreadyStopped,
461 ffi::CUDA_ERROR_STUB_LIBRARY => Self::StubLibrary,
462 ffi::CUDA_ERROR_DEVICE_UNAVAILABLE => Self::DeviceUnavailable,
463 ffi::CUDA_ERROR_NO_DEVICE => Self::NoDevice,
464 ffi::CUDA_ERROR_INVALID_DEVICE => Self::InvalidDevice,
465 ffi::CUDA_ERROR_DEVICE_NOT_LICENSED => Self::DeviceNotLicensed,
466 ffi::CUDA_ERROR_INVALID_IMAGE => Self::InvalidImage,
467 ffi::CUDA_ERROR_INVALID_CONTEXT => Self::InvalidContext,
468 ffi::CUDA_ERROR_CONTEXT_ALREADY_CURRENT => Self::ContextAlreadyCurrent,
469 ffi::CUDA_ERROR_MAP_FAILED => Self::MapFailed,
470 ffi::CUDA_ERROR_UNMAP_FAILED => Self::UnmapFailed,
471 ffi::CUDA_ERROR_ARRAY_IS_MAPPED => Self::ArrayIsMapped,
472 ffi::CUDA_ERROR_ALREADY_MAPPED => Self::AlreadyMapped,
473 ffi::CUDA_ERROR_NO_BINARY_FOR_GPU => Self::NoBinaryForGpu,
474 ffi::CUDA_ERROR_ALREADY_ACQUIRED => Self::AlreadyAcquired,
475 ffi::CUDA_ERROR_NOT_MAPPED => Self::NotMapped,
476 ffi::CUDA_ERROR_NOT_MAPPED_AS_ARRAY => Self::NotMappedAsArray,
477 ffi::CUDA_ERROR_NOT_MAPPED_AS_POINTER => Self::NotMappedAsPointer,
478 ffi::CUDA_ERROR_ECC_UNCORRECTABLE => Self::EccUncorrectable,
479 ffi::CUDA_ERROR_UNSUPPORTED_LIMIT => Self::UnsupportedLimit,
480 ffi::CUDA_ERROR_CONTEXT_ALREADY_IN_USE => Self::ContextAlreadyInUse,
481 ffi::CUDA_ERROR_PEER_ACCESS_UNSUPPORTED => Self::PeerAccessUnsupported,
482 ffi::CUDA_ERROR_INVALID_PTX => Self::InvalidPtx,
483 ffi::CUDA_ERROR_INVALID_GRAPHICS_CONTEXT => Self::InvalidGraphicsContext,
484 ffi::CUDA_ERROR_NVLINK_UNCORRECTABLE => Self::NvlinkUncorrectable,
485 ffi::CUDA_ERROR_JIT_COMPILER_NOT_FOUND => Self::JitCompilerNotFound,
486 ffi::CUDA_ERROR_UNSUPPORTED_PTX_VERSION => Self::UnsupportedPtxVersion,
487 ffi::CUDA_ERROR_JIT_COMPILATION_DISABLED => Self::JitCompilationDisabled,
488 ffi::CUDA_ERROR_UNSUPPORTED_EXEC_AFFINITY => Self::UnsupportedExecAffinity,
489 ffi::CUDA_ERROR_UNSUPPORTED_DEVSIDE_SYNC => Self::UnsupportedDevsideSync,
490 ffi::CUDA_ERROR_INVALID_SOURCE => Self::InvalidSource,
491 ffi::CUDA_ERROR_FILE_NOT_FOUND => Self::FileNotFound,
492 ffi::CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND => Self::SharedObjectSymbolNotFound,
493 ffi::CUDA_ERROR_SHARED_OBJECT_INIT_FAILED => Self::SharedObjectInitFailed,
494 ffi::CUDA_ERROR_OPERATING_SYSTEM => Self::OperatingSystem,
495 ffi::CUDA_ERROR_INVALID_HANDLE => Self::InvalidHandle,
496 ffi::CUDA_ERROR_ILLEGAL_STATE => Self::IllegalState,
497 ffi::CUDA_ERROR_LOSSY_QUERY => Self::LossyQuery,
498 ffi::CUDA_ERROR_NOT_FOUND => Self::NotFound,
499 ffi::CUDA_ERROR_NOT_READY => Self::NotReady,
500 ffi::CUDA_ERROR_ILLEGAL_ADDRESS => Self::IllegalAddress,
501 ffi::CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES => Self::LaunchOutOfResources,
502 ffi::CUDA_ERROR_LAUNCH_TIMEOUT => Self::LaunchTimeout,
503 ffi::CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING => Self::LaunchIncompatibleTexturing,
504 ffi::CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED => Self::PeerAccessAlreadyEnabled,
505 ffi::CUDA_ERROR_PEER_ACCESS_NOT_ENABLED => Self::PeerAccessNotEnabled,
506 ffi::CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE => Self::PrimaryContextActive,
507 ffi::CUDA_ERROR_CONTEXT_IS_DESTROYED => Self::ContextIsDestroyed,
508 ffi::CUDA_ERROR_ASSERT => Self::Assert,
509 ffi::CUDA_ERROR_TOO_MANY_PEERS => Self::TooManyPeers,
510 ffi::CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED => Self::HostMemoryAlreadyRegistered,
511 ffi::CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED => Self::HostMemoryNotRegistered,
512 ffi::CUDA_ERROR_HARDWARE_STACK_ERROR => Self::HardwareStackError,
513 ffi::CUDA_ERROR_ILLEGAL_INSTRUCTION => Self::IllegalInstruction,
514 ffi::CUDA_ERROR_MISALIGNED_ADDRESS => Self::MisalignedAddress,
515 ffi::CUDA_ERROR_INVALID_ADDRESS_SPACE => Self::InvalidAddressSpace,
516 ffi::CUDA_ERROR_INVALID_PC => Self::InvalidPc,
517 ffi::CUDA_ERROR_LAUNCH_FAILED => Self::LaunchFailed,
518 ffi::CUDA_ERROR_COOPERATIVE_LAUNCH_TOO_LARGE => Self::CooperativeLaunchTooLarge,
519 ffi::CUDA_ERROR_NOT_PERMITTED => Self::NotPermitted,
520 ffi::CUDA_ERROR_NOT_SUPPORTED => Self::NotSupported,
521 ffi::CUDA_ERROR_SYSTEM_NOT_READY => Self::SystemNotReady,
522 ffi::CUDA_ERROR_SYSTEM_DRIVER_MISMATCH => Self::SystemDriverMismatch,
523 ffi::CUDA_ERROR_COMPAT_NOT_SUPPORTED_ON_DEVICE => Self::CompatNotSupportedOnDevice,
524 ffi::CUDA_ERROR_MPS_CONNECTION_FAILED => Self::MpsConnectionFailed,
525 ffi::CUDA_ERROR_MPS_RPC_FAILURE => Self::MpsRpcFailure,
526 ffi::CUDA_ERROR_MPS_SERVER_NOT_READY => Self::MpsServerNotReady,
527 ffi::CUDA_ERROR_MPS_MAX_CLIENTS_REACHED => Self::MpsMaxClientsReached,
528 ffi::CUDA_ERROR_MPS_MAX_CONNECTIONS_REACHED => Self::MpsMaxConnectionsReached,
529 ffi::CUDA_ERROR_MPS_CLIENT_TERMINATED => Self::MpsClientTerminated,
530 ffi::CUDA_ERROR_CDP_NOT_SUPPORTED => Self::CdpNotSupported,
531 ffi::CUDA_ERROR_CDP_VERSION_MISMATCH => Self::CdpVersionMismatch,
532 ffi::CUDA_ERROR_STREAM_CAPTURE_UNSUPPORTED => Self::StreamCaptureUnsupported,
533 ffi::CUDA_ERROR_STREAM_CAPTURE_INVALIDATED => Self::StreamCaptureInvalidated,
534 ffi::CUDA_ERROR_STREAM_CAPTURE_MERGE => Self::StreamCaptureMerge,
535 ffi::CUDA_ERROR_STREAM_CAPTURE_UNMATCHED => Self::StreamCaptureUnmatched,
536 ffi::CUDA_ERROR_STREAM_CAPTURE_UNJOINED => Self::StreamCaptureUnjoined,
537 ffi::CUDA_ERROR_STREAM_CAPTURE_ISOLATION => Self::StreamCaptureIsolation,
538 ffi::CUDA_ERROR_STREAM_CAPTURE_IMPLICIT => Self::StreamCaptureImplicit,
539 ffi::CUDA_ERROR_CAPTURED_EVENT => Self::CapturedEvent,
540 ffi::CUDA_ERROR_STREAM_CAPTURE_WRONG_THREAD => Self::StreamCaptureWrongThread,
541 ffi::CUDA_ERROR_TIMEOUT => Self::Timeout,
542 ffi::CUDA_ERROR_GRAPH_EXEC_UPDATE_FAILURE => Self::GraphExecUpdateFailure,
543 ffi::CUDA_ERROR_EXTERNAL_DEVICE => Self::ExternalDevice,
544 ffi::CUDA_ERROR_INVALID_CLUSTER_SIZE => Self::InvalidClusterSize,
545 ffi::CUDA_ERROR_FUNCTION_NOT_LOADED => Self::FunctionNotLoaded,
546 ffi::CUDA_ERROR_INVALID_RESOURCE_TYPE => Self::InvalidResourceType,
547 ffi::CUDA_ERROR_INVALID_RESOURCE_CONFIGURATION => Self::InvalidResourceConfiguration,
548 ffi::CUDA_ERROR_UNKNOWN => Self::Unknown(999),
549 other => Self::Unknown(other),
550 }
551 }
552
553 #[must_use]
580 pub fn is_fatal(&self) -> bool {
581 matches!(
582 self,
583 Self::IllegalAddress
585 | Self::LaunchFailed
586 | Self::HardwareStackError
587 | Self::IllegalInstruction
588 | Self::MisalignedAddress
589 | Self::InvalidAddressSpace
590 | Self::InvalidPc
591 | Self::Assert
592 | Self::EccUncorrectable
593 | Self::NvlinkUncorrectable
594 | Self::ContextIsDestroyed
596 | Self::Deinitialized
597 )
598 }
599
600 #[must_use]
614 pub fn is_usage_error(&self) -> bool {
615 matches!(
616 self,
617 Self::InvalidValue
618 | Self::InvalidDevice
619 | Self::InvalidContext
620 | Self::InvalidHandle
621 | Self::InvalidImage
622 | Self::InvalidPtx
623 | Self::InvalidSource
624 | Self::InvalidClusterSize
625 | Self::NoDevice
626 | Self::UnsupportedLimit
627 | Self::NotSupported
628 | Self::NotPermitted
629 )
630 }
631
632 #[allow(clippy::too_many_lines)]
634 pub fn as_raw(&self) -> u32 {
635 match self {
636 Self::InvalidValue => ffi::CUDA_ERROR_INVALID_VALUE,
637 Self::OutOfMemory => ffi::CUDA_ERROR_OUT_OF_MEMORY,
638 Self::NotInitialized => ffi::CUDA_ERROR_NOT_INITIALIZED,
639 Self::Deinitialized => ffi::CUDA_ERROR_DEINITIALIZED,
640 Self::ProfilerDisabled => ffi::CUDA_ERROR_PROFILER_DISABLED,
641 Self::ProfilerNotInitialized => ffi::CUDA_ERROR_PROFILER_NOT_INITIALIZED,
642 Self::ProfilerAlreadyStarted => ffi::CUDA_ERROR_PROFILER_ALREADY_STARTED,
643 Self::ProfilerAlreadyStopped => ffi::CUDA_ERROR_PROFILER_ALREADY_STOPPED,
644 Self::StubLibrary => ffi::CUDA_ERROR_STUB_LIBRARY,
645 Self::DeviceUnavailable => ffi::CUDA_ERROR_DEVICE_UNAVAILABLE,
646 Self::NoDevice => ffi::CUDA_ERROR_NO_DEVICE,
647 Self::InvalidDevice => ffi::CUDA_ERROR_INVALID_DEVICE,
648 Self::DeviceNotLicensed => ffi::CUDA_ERROR_DEVICE_NOT_LICENSED,
649 Self::InvalidImage => ffi::CUDA_ERROR_INVALID_IMAGE,
650 Self::InvalidContext => ffi::CUDA_ERROR_INVALID_CONTEXT,
651 Self::ContextAlreadyCurrent => ffi::CUDA_ERROR_CONTEXT_ALREADY_CURRENT,
652 Self::MapFailed => ffi::CUDA_ERROR_MAP_FAILED,
653 Self::UnmapFailed => ffi::CUDA_ERROR_UNMAP_FAILED,
654 Self::ArrayIsMapped => ffi::CUDA_ERROR_ARRAY_IS_MAPPED,
655 Self::AlreadyMapped => ffi::CUDA_ERROR_ALREADY_MAPPED,
656 Self::NoBinaryForGpu => ffi::CUDA_ERROR_NO_BINARY_FOR_GPU,
657 Self::AlreadyAcquired => ffi::CUDA_ERROR_ALREADY_ACQUIRED,
658 Self::NotMapped => ffi::CUDA_ERROR_NOT_MAPPED,
659 Self::NotMappedAsArray => ffi::CUDA_ERROR_NOT_MAPPED_AS_ARRAY,
660 Self::NotMappedAsPointer => ffi::CUDA_ERROR_NOT_MAPPED_AS_POINTER,
661 Self::EccUncorrectable => ffi::CUDA_ERROR_ECC_UNCORRECTABLE,
662 Self::UnsupportedLimit => ffi::CUDA_ERROR_UNSUPPORTED_LIMIT,
663 Self::ContextAlreadyInUse => ffi::CUDA_ERROR_CONTEXT_ALREADY_IN_USE,
664 Self::PeerAccessUnsupported => ffi::CUDA_ERROR_PEER_ACCESS_UNSUPPORTED,
665 Self::InvalidPtx => ffi::CUDA_ERROR_INVALID_PTX,
666 Self::InvalidGraphicsContext => ffi::CUDA_ERROR_INVALID_GRAPHICS_CONTEXT,
667 Self::NvlinkUncorrectable => ffi::CUDA_ERROR_NVLINK_UNCORRECTABLE,
668 Self::JitCompilerNotFound => ffi::CUDA_ERROR_JIT_COMPILER_NOT_FOUND,
669 Self::UnsupportedPtxVersion => ffi::CUDA_ERROR_UNSUPPORTED_PTX_VERSION,
670 Self::JitCompilationDisabled => ffi::CUDA_ERROR_JIT_COMPILATION_DISABLED,
671 Self::UnsupportedExecAffinity => ffi::CUDA_ERROR_UNSUPPORTED_EXEC_AFFINITY,
672 Self::UnsupportedDevsideSync => ffi::CUDA_ERROR_UNSUPPORTED_DEVSIDE_SYNC,
673 Self::InvalidSource => ffi::CUDA_ERROR_INVALID_SOURCE,
674 Self::FileNotFound => ffi::CUDA_ERROR_FILE_NOT_FOUND,
675 Self::SharedObjectSymbolNotFound => ffi::CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND,
676 Self::SharedObjectInitFailed => ffi::CUDA_ERROR_SHARED_OBJECT_INIT_FAILED,
677 Self::OperatingSystem => ffi::CUDA_ERROR_OPERATING_SYSTEM,
678 Self::InvalidHandle => ffi::CUDA_ERROR_INVALID_HANDLE,
679 Self::IllegalState => ffi::CUDA_ERROR_ILLEGAL_STATE,
680 Self::LossyQuery => ffi::CUDA_ERROR_LOSSY_QUERY,
681 Self::NotFound => ffi::CUDA_ERROR_NOT_FOUND,
682 Self::NotReady => ffi::CUDA_ERROR_NOT_READY,
683 Self::IllegalAddress => ffi::CUDA_ERROR_ILLEGAL_ADDRESS,
684 Self::LaunchOutOfResources => ffi::CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES,
685 Self::LaunchTimeout => ffi::CUDA_ERROR_LAUNCH_TIMEOUT,
686 Self::LaunchIncompatibleTexturing => ffi::CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING,
687 Self::PeerAccessAlreadyEnabled => ffi::CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED,
688 Self::PeerAccessNotEnabled => ffi::CUDA_ERROR_PEER_ACCESS_NOT_ENABLED,
689 Self::PrimaryContextActive => ffi::CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE,
690 Self::ContextIsDestroyed => ffi::CUDA_ERROR_CONTEXT_IS_DESTROYED,
691 Self::Assert => ffi::CUDA_ERROR_ASSERT,
692 Self::TooManyPeers => ffi::CUDA_ERROR_TOO_MANY_PEERS,
693 Self::HostMemoryAlreadyRegistered => ffi::CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED,
694 Self::HostMemoryNotRegistered => ffi::CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED,
695 Self::HardwareStackError => ffi::CUDA_ERROR_HARDWARE_STACK_ERROR,
696 Self::IllegalInstruction => ffi::CUDA_ERROR_ILLEGAL_INSTRUCTION,
697 Self::MisalignedAddress => ffi::CUDA_ERROR_MISALIGNED_ADDRESS,
698 Self::InvalidAddressSpace => ffi::CUDA_ERROR_INVALID_ADDRESS_SPACE,
699 Self::InvalidPc => ffi::CUDA_ERROR_INVALID_PC,
700 Self::LaunchFailed => ffi::CUDA_ERROR_LAUNCH_FAILED,
701 Self::CooperativeLaunchTooLarge => ffi::CUDA_ERROR_COOPERATIVE_LAUNCH_TOO_LARGE,
702 Self::NotPermitted => ffi::CUDA_ERROR_NOT_PERMITTED,
703 Self::NotSupported => ffi::CUDA_ERROR_NOT_SUPPORTED,
704 Self::SystemNotReady => ffi::CUDA_ERROR_SYSTEM_NOT_READY,
705 Self::SystemDriverMismatch => ffi::CUDA_ERROR_SYSTEM_DRIVER_MISMATCH,
706 Self::CompatNotSupportedOnDevice => ffi::CUDA_ERROR_COMPAT_NOT_SUPPORTED_ON_DEVICE,
707 Self::MpsConnectionFailed => ffi::CUDA_ERROR_MPS_CONNECTION_FAILED,
708 Self::MpsRpcFailure => ffi::CUDA_ERROR_MPS_RPC_FAILURE,
709 Self::MpsServerNotReady => ffi::CUDA_ERROR_MPS_SERVER_NOT_READY,
710 Self::MpsMaxClientsReached => ffi::CUDA_ERROR_MPS_MAX_CLIENTS_REACHED,
711 Self::MpsMaxConnectionsReached => ffi::CUDA_ERROR_MPS_MAX_CONNECTIONS_REACHED,
712 Self::MpsClientTerminated => ffi::CUDA_ERROR_MPS_CLIENT_TERMINATED,
713 Self::CdpNotSupported => ffi::CUDA_ERROR_CDP_NOT_SUPPORTED,
714 Self::CdpVersionMismatch => ffi::CUDA_ERROR_CDP_VERSION_MISMATCH,
715 Self::StreamCaptureUnsupported => ffi::CUDA_ERROR_STREAM_CAPTURE_UNSUPPORTED,
716 Self::StreamCaptureInvalidated => ffi::CUDA_ERROR_STREAM_CAPTURE_INVALIDATED,
717 Self::StreamCaptureMerge => ffi::CUDA_ERROR_STREAM_CAPTURE_MERGE,
718 Self::StreamCaptureUnmatched => ffi::CUDA_ERROR_STREAM_CAPTURE_UNMATCHED,
719 Self::StreamCaptureUnjoined => ffi::CUDA_ERROR_STREAM_CAPTURE_UNJOINED,
720 Self::StreamCaptureIsolation => ffi::CUDA_ERROR_STREAM_CAPTURE_ISOLATION,
721 Self::StreamCaptureImplicit => ffi::CUDA_ERROR_STREAM_CAPTURE_IMPLICIT,
722 Self::CapturedEvent => ffi::CUDA_ERROR_CAPTURED_EVENT,
723 Self::StreamCaptureWrongThread => ffi::CUDA_ERROR_STREAM_CAPTURE_WRONG_THREAD,
724 Self::Timeout => ffi::CUDA_ERROR_TIMEOUT,
725 Self::GraphExecUpdateFailure => ffi::CUDA_ERROR_GRAPH_EXEC_UPDATE_FAILURE,
726 Self::ExternalDevice => ffi::CUDA_ERROR_EXTERNAL_DEVICE,
727 Self::InvalidClusterSize => ffi::CUDA_ERROR_INVALID_CLUSTER_SIZE,
728 Self::FunctionNotLoaded => ffi::CUDA_ERROR_FUNCTION_NOT_LOADED,
729 Self::InvalidResourceType => ffi::CUDA_ERROR_INVALID_RESOURCE_TYPE,
730 Self::InvalidResourceConfiguration => ffi::CUDA_ERROR_INVALID_RESOURCE_CONFIGURATION,
731 Self::JitFailed { source, .. } => source.as_raw(),
733 Self::Unknown(code) => *code,
734 }
735 }
736}
737
738pub type CudaResult<T> = Result<T, CudaError>;
744
745#[inline(always)]
754pub fn check(result: u32) -> CudaResult<()> {
755 if result == 0 {
756 Ok(())
757 } else {
758 Err(CudaError::from_raw(result))
759 }
760}
761
762#[macro_export]
777macro_rules! cuda_call {
778 ($expr:expr) => {
779 $crate::error::check(unsafe { $expr })
780 };
781}
782
783#[derive(Debug, thiserror::Error)]
789pub enum DriverLoadError {
790 #[error("CUDA driver library not found (tried: {candidates:?}): {last_error}")]
792 LibraryNotFound {
793 candidates: Vec<String>,
795 last_error: String,
797 },
798
799 #[error("failed to load symbol '{symbol}': {reason}")]
801 SymbolNotFound {
802 symbol: &'static str,
804 reason: String,
806 },
807
808 #[error("cuInit(0) failed with CUDA error code {code}")]
815 InitializationFailed {
816 code: u32,
818 },
819
820 #[error("CUDA driver not supported on this platform")]
822 UnsupportedPlatform,
823}
824
825#[cfg(test)]
830mod tests {
831 use super::*;
832
833 #[test]
834 fn test_check_success() {
835 assert!(check(0).is_ok());
836 }
837
838 #[test]
839 fn test_check_error() {
840 let result = check(1);
841 assert!(result.is_err());
842 assert_eq!(result.err(), Some(CudaError::InvalidValue));
843 }
844
845 #[test]
846 fn test_check_out_of_memory() {
847 let result = check(2);
848 assert_eq!(result.err(), Some(CudaError::OutOfMemory));
849 }
850
851 #[test]
852 fn test_check_not_initialized() {
853 let result = check(3);
854 assert_eq!(result.err(), Some(CudaError::NotInitialized));
855 }
856
857 #[test]
858 fn test_from_raw_roundtrip() {
859 let codes: &[u32] = &[
861 1, 2, 3, 4, 5, 6, 7, 8, 34, 46, 100, 101, 102, 200, 201, 202, 205, 206, 207, 208, 209,
862 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 300,
863 301, 302, 303, 304, 400, 401, 402, 500, 600, 700, 701, 702, 703, 704, 705, 708, 709,
864 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 800, 801, 802, 803, 804, 805,
865 806, 807, 808, 809, 810, 811, 812, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909,
866 910, 911, 912, 913, 914, 915, 999,
867 ];
868 for &code in codes {
869 let err = CudaError::from_raw(code);
870 assert_eq!(
871 err.as_raw(),
872 code,
873 "round-trip failed for code {code}: got {:?}",
874 err
875 );
876 }
877 }
878
879 #[test]
880 fn test_unknown_code() {
881 let err = CudaError::from_raw(12345);
882 assert_eq!(err, CudaError::Unknown(12345));
883 assert_eq!(err.as_raw(), 12345);
884 }
885
886 #[test]
887 fn test_unknown_code_display() {
888 let err = CudaError::from_raw(12345);
889 let msg = format!("{err}");
890 assert!(
891 msg.contains("12345"),
892 "display should contain the code: {msg}"
893 );
894 }
895
896 #[test]
897 fn test_error_display_messages() {
898 assert_eq!(
899 format!("{}", CudaError::InvalidValue),
900 "CUDA: invalid value"
901 );
902 assert_eq!(
903 format!("{}", CudaError::OutOfMemory),
904 "CUDA: out of device memory"
905 );
906 assert_eq!(
907 format!("{}", CudaError::LaunchFailed),
908 "CUDA: kernel launch failed"
909 );
910 assert_eq!(
911 format!("{}", CudaError::NotReady),
912 "CUDA: not ready (async operation pending)"
913 );
914 }
915
916 #[test]
917 fn test_error_is_clone() {
918 let err = CudaError::InvalidValue;
919 let cloned = err.clone();
920 assert_eq!(err, cloned);
921 }
922
923 #[test]
924 fn test_error_implements_std_error() {
925 fn assert_error<T: std::error::Error>() {}
926 assert_error::<CudaError>();
927 assert_error::<DriverLoadError>();
928 }
929
930 #[test]
931 fn test_driver_load_error_display() {
932 let err = DriverLoadError::LibraryNotFound {
933 candidates: vec!["libcuda.so".to_string()],
934 last_error: "no such file or directory".to_string(),
935 };
936 let msg = format!("{err}");
937 assert!(msg.contains("libcuda.so"));
938
939 let err = DriverLoadError::SymbolNotFound {
940 symbol: "cuInit",
941 reason: "not found".to_string(),
942 };
943 let msg = format!("{err}");
944 assert!(msg.contains("cuInit"));
945
946 let err = DriverLoadError::UnsupportedPlatform;
947 let msg = format!("{err}");
948 assert!(msg.contains("not supported"));
949 }
950
951 #[test]
952 fn test_cuda_call_macro() {
953 unsafe fn fake_success() -> u32 {
955 0
956 }
957 unsafe fn fake_launch_failed() -> u32 {
958 719
959 }
960
961 let result = cuda_call!(fake_success());
962 assert!(result.is_ok());
963
964 let result = cuda_call!(fake_launch_failed());
965 assert_eq!(result.err(), Some(CudaError::LaunchFailed));
966 }
967
968 #[test]
969 fn test_error_hash() {
970 use std::collections::HashSet;
971 let mut set = HashSet::new();
972 set.insert(CudaError::InvalidValue);
973 set.insert(CudaError::OutOfMemory);
974 set.insert(CudaError::InvalidValue); assert_eq!(set.len(), 2);
976 }
977
978 #[test]
979 fn test_cuda_result_type_alias() {
980 fn returns_ok() -> CudaResult<i32> {
981 Ok(42)
982 }
983 fn returns_err() -> CudaResult<i32> {
984 Err(CudaError::NoDevice)
985 }
986 assert_eq!(returns_ok().ok(), Some(42));
987 assert_eq!(returns_err().err(), Some(CudaError::NoDevice));
988 }
989
990 #[test]
996 fn test_all_common_cuda_error_variants_have_display() {
997 let errors: &[CudaError] = &[
998 CudaError::InvalidValue,
1000 CudaError::OutOfMemory,
1001 CudaError::NotInitialized,
1002 CudaError::Deinitialized,
1003 CudaError::ProfilerDisabled,
1004 CudaError::ProfilerNotInitialized,
1005 CudaError::ProfilerAlreadyStarted,
1006 CudaError::ProfilerAlreadyStopped,
1007 CudaError::StubLibrary,
1009 CudaError::DeviceUnavailable,
1010 CudaError::NoDevice,
1012 CudaError::InvalidDevice,
1013 CudaError::DeviceNotLicensed,
1014 CudaError::InvalidImage,
1016 CudaError::InvalidContext,
1017 CudaError::ContextAlreadyCurrent,
1018 CudaError::MapFailed,
1019 CudaError::UnmapFailed,
1020 CudaError::EccUncorrectable,
1021 CudaError::InvalidSource,
1023 CudaError::FileNotFound,
1024 CudaError::SharedObjectSymbolNotFound,
1025 CudaError::InvalidHandle,
1027 CudaError::IllegalState,
1028 CudaError::NotFound,
1029 CudaError::NotReady,
1031 CudaError::IllegalAddress,
1033 CudaError::LaunchOutOfResources,
1034 CudaError::LaunchTimeout,
1035 CudaError::LaunchFailed,
1036 CudaError::CooperativeLaunchTooLarge,
1037 CudaError::NotPermitted,
1039 CudaError::NotSupported,
1040 CudaError::HardwareStackError,
1042 CudaError::IllegalInstruction,
1043 CudaError::MisalignedAddress,
1044 CudaError::InvalidAddressSpace,
1045 CudaError::InvalidPc,
1046 CudaError::PeerAccessAlreadyEnabled,
1048 CudaError::PeerAccessNotEnabled,
1049 CudaError::ContextIsDestroyed,
1050 CudaError::StreamCaptureUnsupported,
1052 CudaError::StreamCaptureInvalidated,
1053 CudaError::InvalidClusterSize,
1054 CudaError::FunctionNotLoaded,
1055 CudaError::Unknown(99999),
1057 ];
1058 for err in errors {
1059 let display = format!("{err}");
1060 assert!(
1061 !display.is_empty(),
1062 "CudaError::{err:?} has an empty Display string"
1063 );
1064 }
1065 }
1066
1067 #[test]
1069 fn test_cuda_error_from_result_code() {
1070 let pairs: &[(u32, CudaError)] = &[
1071 (1, CudaError::InvalidValue),
1072 (2, CudaError::OutOfMemory),
1073 (3, CudaError::NotInitialized),
1074 (4, CudaError::Deinitialized),
1075 (100, CudaError::NoDevice),
1076 (101, CudaError::InvalidDevice),
1077 (200, CudaError::InvalidImage),
1078 (201, CudaError::InvalidContext),
1079 (400, CudaError::InvalidHandle),
1080 (500, CudaError::NotFound),
1081 (600, CudaError::NotReady),
1082 (700, CudaError::IllegalAddress),
1083 (701, CudaError::LaunchOutOfResources),
1084 (702, CudaError::LaunchTimeout),
1085 (719, CudaError::LaunchFailed),
1086 (800, CudaError::NotPermitted),
1087 (801, CudaError::NotSupported),
1088 (912, CudaError::InvalidClusterSize),
1089 (999, CudaError::Unknown(999)),
1090 ];
1091 for &(code, ref expected) in pairs {
1092 let got = CudaError::from_raw(code);
1093 assert_eq!(
1094 &got, expected,
1095 "from_raw({code}) should be {expected:?}, got {got:?}"
1096 );
1097 assert_eq!(
1098 got.as_raw(),
1099 code,
1100 "as_raw() round-trip failed for code {code}"
1101 );
1102 }
1103 }
1104
1105 #[test]
1107 fn test_cuda_error_is_fatal() {
1108 let fatal: &[CudaError] = &[
1110 CudaError::IllegalAddress,
1111 CudaError::LaunchFailed,
1112 CudaError::HardwareStackError,
1113 CudaError::IllegalInstruction,
1114 CudaError::MisalignedAddress,
1115 CudaError::InvalidAddressSpace,
1116 CudaError::InvalidPc,
1117 CudaError::Assert,
1118 CudaError::EccUncorrectable,
1119 CudaError::NvlinkUncorrectable,
1120 CudaError::ContextIsDestroyed,
1121 CudaError::Deinitialized,
1122 ];
1123 for err in fatal {
1124 assert!(
1125 err.is_fatal(),
1126 "CudaError::{err:?} should be classified as fatal"
1127 );
1128 }
1129
1130 let non_fatal: &[CudaError] = &[
1132 CudaError::InvalidValue,
1133 CudaError::OutOfMemory,
1134 CudaError::NotInitialized,
1135 CudaError::NoDevice,
1136 CudaError::NotReady,
1137 CudaError::LaunchOutOfResources,
1138 CudaError::LaunchTimeout,
1139 CudaError::NotPermitted,
1140 CudaError::NotSupported,
1141 CudaError::InvalidClusterSize,
1142 CudaError::Unknown(99),
1143 ];
1144 for err in non_fatal {
1145 assert!(
1146 !err.is_fatal(),
1147 "CudaError::{err:?} should NOT be classified as fatal"
1148 );
1149 }
1150 }
1151
1152 #[test]
1154 fn test_cuda_error_is_usage_error() {
1155 let usage: &[CudaError] = &[
1156 CudaError::InvalidValue,
1157 CudaError::InvalidDevice,
1158 CudaError::InvalidContext,
1159 CudaError::InvalidHandle,
1160 CudaError::NoDevice,
1161 ];
1162 for err in usage {
1163 assert!(
1164 err.is_usage_error(),
1165 "CudaError::{err:?} should be a usage error"
1166 );
1167 }
1168
1169 let non_usage: &[CudaError] = &[
1170 CudaError::OutOfMemory,
1171 CudaError::LaunchFailed,
1172 CudaError::IllegalAddress,
1173 CudaError::NotReady,
1174 ];
1175 for err in non_usage {
1176 assert!(
1177 !err.is_usage_error(),
1178 "CudaError::{err:?} should NOT be a usage error"
1179 );
1180 }
1181 }
1182
1183 #[test]
1185 fn test_fatal_and_usage_error_are_disjoint() {
1186 let all_errors: &[CudaError] = &[
1188 CudaError::InvalidValue,
1189 CudaError::OutOfMemory,
1190 CudaError::LaunchFailed,
1191 CudaError::IllegalAddress,
1192 CudaError::HardwareStackError,
1193 CudaError::NotReady,
1194 CudaError::InvalidDevice,
1195 ];
1196 for err in all_errors {
1197 assert!(
1198 !(err.is_fatal() && err.is_usage_error()),
1199 "CudaError::{err:?} cannot be both fatal and a usage error"
1200 );
1201 }
1202 }
1203
1204 #[test]
1207 fn test_error_injection_simulation() {
1208 let injected = check(700);
1210 let err = injected.expect_err("error code 700 must be an Err");
1211 assert_eq!(err, CudaError::IllegalAddress);
1212 assert!(err.is_fatal(), "IllegalAddress must be fatal");
1213 assert!(!err.is_usage_error());
1214
1215 let injected = check(1);
1217 let err = injected.expect_err("error code 1 must be an Err");
1218 assert_eq!(err, CudaError::InvalidValue);
1219 assert!(!err.is_fatal(), "InvalidValue must not be fatal");
1220 assert!(err.is_usage_error());
1221
1222 let injected = check(55555);
1224 let err = injected.expect_err("unknown code must be an Err");
1225 assert!(matches!(err, CudaError::Unknown(55555)));
1226 assert!(!err.is_fatal());
1227 assert!(!err.is_usage_error());
1228 }
1229}