All Classes Files Functions Enumerations Enumerator Pages
error.hpp
1 /*
2  * Copyright (c) 2021-2025, NVIDIA CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <cstring>
19 #include <exception>
20 #include <system_error>
21 
22 #include <kvikio/shim/cuda.hpp>
23 #include <kvikio/shim/cufile_h_wrapper.hpp>
24 
25 namespace kvikio {
26 
27 struct CUfileException : public std::runtime_error {
28  using std::runtime_error::runtime_error;
29 };
30 
31 #ifndef CUDA_DRIVER_TRY
32 #define CUDA_DRIVER_TRY(...) \
33  GET_CUDA_DRIVER_TRY_MACRO(__VA_ARGS__, CUDA_DRIVER_TRY_2, CUDA_DRIVER_TRY_1) \
34  (__VA_ARGS__)
35 #define GET_CUDA_DRIVER_TRY_MACRO(_1, _2, NAME, ...) NAME
36 #define CUDA_DRIVER_TRY_2(_call, _exception_type) \
37  do { \
38  kvikio::detail::cuda_driver_try_2<_exception_type>(_call, __LINE__, __FILE__); \
39  } while (0)
40 #define CUDA_DRIVER_TRY_1(_call) CUDA_DRIVER_TRY_2(_call, kvikio::CUfileException)
41 #endif
42 
43 #ifndef CUFILE_TRY
44 #define CUFILE_TRY(...) \
45  GET_CUFILE_TRY_MACRO(__VA_ARGS__, CUFILE_TRY_2, CUFILE_TRY_1) \
46  (__VA_ARGS__)
47 #define GET_CUFILE_TRY_MACRO(_1, _2, NAME, ...) NAME
48 #define CUFILE_TRY_2(_call, _exception_type) \
49  do { \
50  kvikio::detail::cufile_try_2<_exception_type>(_call, __LINE__, __FILE__); \
51  } while (0)
52 #define CUFILE_TRY_1(_call) CUFILE_TRY_2(_call, kvikio::CUfileException)
53 #endif
54 
55 #ifndef CUFILE_CHECK_BYTES_DONE
56 #define CUFILE_CHECK_BYTES_DONE(...) \
57  GET_CUFILE_CHECK_BYTES_DONE_MACRO( \
58  __VA_ARGS__, CUFILE_CHECK_BYTES_DONE_2, CUFILE_CHECK_BYTES_DONE_1) \
59  (__VA_ARGS__)
60 #define GET_CUFILE_CHECK_BYTES_DONE_MACRO(_1, _2, NAME, ...) NAME
61 #define CUFILE_CHECK_BYTES_DONE_2(_nbytes_done, _exception_type) \
62  do { \
63  kvikio::detail::cufile_check_bytes_done_2<_exception_type>(_nbytes_done, __LINE__, __FILE__); \
64  } while (0)
65 #define CUFILE_CHECK_BYTES_DONE_1(_call) CUFILE_CHECK_BYTES_DONE_2(_call, kvikio::CUfileException)
66 #endif
67 
68 namespace detail {
69 template <typename Exception>
70 void cuda_driver_try_2(CUresult error, int line_number, const char* filename)
71 {
72  if (error == CUDA_ERROR_STUB_LIBRARY) {
73  throw Exception{std::string{"CUDA error at: "} + std::string(filename) + ":" +
74  KVIKIO_STRINGIFY(line_number) +
75  ": CUDA_ERROR_STUB_LIBRARY("
76  "The CUDA driver loaded is a stub library)"};
77  }
78  if (error != CUDA_SUCCESS) {
79  const char* err_name = nullptr;
80  const char* err_str = nullptr;
81  CUresult err_name_status = cudaAPI::instance().GetErrorName(error, &err_name);
82  CUresult err_str_status = cudaAPI::instance().GetErrorString(error, &err_str);
83  if (err_name_status == CUDA_ERROR_INVALID_VALUE) { err_name = "unknown"; }
84  if (err_str_status == CUDA_ERROR_INVALID_VALUE) { err_str = "unknown"; }
85  throw Exception{std::string{"CUDA error at: "} + filename + ":" +
86  KVIKIO_STRINGIFY(line_number) + ": " + std::string(err_name) + "(" +
87  std::string(err_str) + ")"};
88  }
89 }
90 
91 template <typename Exception>
92 void cufile_try_2(CUfileError_t error, int line_number, const char* filename)
93 {
94  if (error.err != CU_FILE_SUCCESS) {
95  if (error.err == CU_FILE_CUDA_DRIVER_ERROR) {
96  CUresult const cuda_error = error.cu_err;
97  CUDA_DRIVER_TRY(cuda_error);
98  }
99  throw Exception{std::string{"cuFile error at: "} + filename + ":" +
100  KVIKIO_STRINGIFY(line_number) + ": " +
101  cufileop_status_error((CUfileOpError)std::abs(error.err))};
102  }
103 }
104 
105 template <typename Exception>
106 void cufile_check_bytes_done_2(ssize_t nbytes_done, int line_number, const char* filename)
107 {
108  if (nbytes_done < 0) {
109  auto const err = std::abs(nbytes_done);
110  auto const msg = (err > CUFILEOP_BASE_ERR)
111  ? std::string(cufileop_status_error((CUfileOpError)err))
112  : std::string(std::strerror(err));
113  throw Exception{std::string{"cuFile error at: "} + filename + ":" +
114  KVIKIO_STRINGIFY(line_number) + ": " + msg};
115  }
116 }
117 
118 } // namespace detail
119 
120 } // namespace kvikio