All Classes Namespaces Functions Enumerations Enumerator Modules 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 <sstream>
20 #include <stdexcept>
21 #include <string>
22 #include <system_error>
23 
24 #include <kvikio/shim/cuda.hpp>
25 #include <kvikio/shim/cufile_h_wrapper.hpp>
26 
27 namespace kvikio {
28 
29 struct CUfileException : public std::runtime_error {
30  using std::runtime_error::runtime_error;
31 };
32 
33 class GenericSystemError : public std::system_error {
34  public:
35  GenericSystemError(const std::string& msg);
36  GenericSystemError(const char* msg);
37  GenericSystemError(const GenericSystemError& other) = default;
38  GenericSystemError& operator=(const GenericSystemError& other) = default;
39  virtual ~GenericSystemError() noexcept = default;
40 };
41 
42 #ifndef CUDA_DRIVER_TRY
68 #define CUDA_DRIVER_TRY(...) \
69  GET_CUDA_DRIVER_TRY_MACRO(__VA_ARGS__, CUDA_DRIVER_TRY_2, CUDA_DRIVER_TRY_1) \
70  (__VA_ARGS__)
73 #define GET_CUDA_DRIVER_TRY_MACRO(_1, _2, NAME, ...) NAME
74 #define CUDA_DRIVER_TRY_2(_call, _exception_type) \
75  do { \
76  kvikio::detail::cuda_driver_try_2<_exception_type>(_call, __LINE__, __FILE__); \
77  } while (0)
78 #define CUDA_DRIVER_TRY_1(_call) CUDA_DRIVER_TRY_2(_call, kvikio::CUfileException)
79 #endif
80 
81 #ifndef CUFILE_TRY
107 #define CUFILE_TRY(...) \
108  GET_CUFILE_TRY_MACRO(__VA_ARGS__, CUFILE_TRY_2, CUFILE_TRY_1) \
109  (__VA_ARGS__)
112 #define GET_CUFILE_TRY_MACRO(_1, _2, NAME, ...) NAME
113 #define CUFILE_TRY_2(_call, _exception_type) \
114  do { \
115  kvikio::detail::cufile_try_2<_exception_type>(_call, __LINE__, __FILE__); \
116  } while (0)
117 #define CUFILE_TRY_1(_call) CUFILE_TRY_2(_call, kvikio::CUfileException)
118 #endif
119 
120 #ifndef CUFILE_CHECK_BYTES_DONE
121 #define CUFILE_CHECK_BYTES_DONE(...) \
122  GET_CUFILE_CHECK_BYTES_DONE_MACRO( \
123  __VA_ARGS__, CUFILE_CHECK_BYTES_DONE_2, CUFILE_CHECK_BYTES_DONE_1) \
124  (__VA_ARGS__)
125 #define GET_CUFILE_CHECK_BYTES_DONE_MACRO(_1, _2, NAME, ...) NAME
126 #define CUFILE_CHECK_BYTES_DONE_2(_nbytes_done, _exception_type) \
127  do { \
128  kvikio::detail::cufile_check_bytes_done_2<_exception_type>(_nbytes_done, __LINE__, __FILE__); \
129  } while (0)
130 #define CUFILE_CHECK_BYTES_DONE_1(_call) CUFILE_CHECK_BYTES_DONE_2(_call, kvikio::CUfileException)
131 #endif
132 
133 namespace detail {
134 template <typename Exception>
135 void cuda_driver_try_2(CUresult error, int line_number, char const* filename)
136 {
137  if (error == CUDA_ERROR_STUB_LIBRARY) {
138  throw Exception{std::string{"CUDA error at: "} + std::string(filename) + ":" +
139  std::to_string(line_number) +
140  ": CUDA_ERROR_STUB_LIBRARY("
141  "The CUDA driver loaded is a stub library)"};
142  }
143  if (error != CUDA_SUCCESS) {
144  char const* err_name = nullptr;
145  char const* err_str = nullptr;
146  CUresult err_name_status = cudaAPI::instance().GetErrorName(error, &err_name);
147  CUresult err_str_status = cudaAPI::instance().GetErrorString(error, &err_str);
148  if (err_name_status == CUDA_ERROR_INVALID_VALUE) { err_name = "unknown"; }
149  if (err_str_status == CUDA_ERROR_INVALID_VALUE) { err_str = "unknown"; }
150  throw Exception{std::string{"CUDA error at: "} + filename + ":" + std::to_string(line_number) +
151  ": " + std::string(err_name) + "(" + std::string(err_str) + ")"};
152  }
153 }
154 
155 template <typename Exception>
156 void cufile_try_2(CUfileError_t error, int line_number, char const* filename)
157 {
158  if (error.err != CU_FILE_SUCCESS) {
159  if (error.err == CU_FILE_CUDA_DRIVER_ERROR) {
160  CUresult const cuda_error = error.cu_err;
161  CUDA_DRIVER_TRY(cuda_error);
162  }
163  throw Exception{std::string{"cuFile error at: "} + filename + ":" +
164  std::to_string(line_number) + ": " +
165  cufileop_status_error((CUfileOpError)std::abs(error.err))};
166  }
167 }
168 
169 template <typename Exception>
170 void cufile_check_bytes_done_2(ssize_t nbytes_done, int line_number, char const* filename)
171 {
172  if (nbytes_done < 0) {
173  auto const err = std::abs(nbytes_done);
174  auto const msg = (err > CUFILEOP_BASE_ERR)
175  ? std::string(cufileop_status_error((CUfileOpError)err))
176  : std::string(std::strerror(err));
177  throw Exception{std::string{"cuFile error at: "} + filename + ":" +
178  std::to_string(line_number) + ": " + msg};
179  }
180 }
181 
182 #define KVIKIO_LOG_ERROR(err_msg) kvikio::detail::log_error(err_msg, __LINE__, __FILE__)
183 void log_error(std::string_view err_msg, int line_number, char const* filename);
184 
185 } // namespace detail
186 
216 #define KVIKIO_EXPECT(...) \
217  GET_KVIKIO_EXPECT_MACRO(__VA_ARGS__, KVIKIO_EXPECT_3, KVIKIO_EXPECT_2)(__VA_ARGS__)
220 #define GET_KVIKIO_EXPECT_MACRO(_1, _2, _3, NAME, ...) NAME
221 
222 #define KVIKIO_EXPECT_3(_condition, _msg, _exception_type) \
223  do { \
224  kvikio::detail::kvikio_assertion<_exception_type>(_condition, _msg, __LINE__, __FILE__); \
225  } while (0)
226 
227 #define KVIKIO_EXPECT_2(_condition, _msg) KVIKIO_EXPECT_3(_condition, _msg, kvikio::CUfileException)
228 
252 #define KVIKIO_FAIL(...) \
253  GET_KVIKIO_FAIL_MACRO(__VA_ARGS__, KVIKIO_FAIL_2, KVIKIO_FAIL_1)(__VA_ARGS__)
256 #define GET_KVIKIO_FAIL_MACRO(_1, _2, NAME, ...) NAME
257 
258 #define KVIKIO_FAIL_2(_msg, _exception_type) \
259  do { \
260  kvikio::detail::kvikio_assertion<_exception_type>(false, _msg, __LINE__, __FILE__); \
261  } while (0)
262 
263 #define KVIKIO_FAIL_1(_msg) KVIKIO_FAIL_2(_msg, kvikio::CUfileException)
264 
265 namespace detail {
266 template <typename Exception>
267 void kvikio_assertion(bool condition, const char* msg, int line_number, char const* filename)
268 {
269  if (!condition) {
270  std::stringstream ss;
271  ss << "KvikIO failure at: " << filename << ":" << line_number << ": ";
272  if (msg == nullptr) {
273  ss << "(no message)";
274  } else {
275  ss << msg;
276  }
277  throw Exception{ss.str()};
278  };
279 }
280 
281 template <typename Exception>
282 void kvikio_assertion(bool condition, const std::string& msg, int line_number, char const* filename)
283 {
284  kvikio_assertion<Exception>(condition, msg.c_str(), line_number, filename);
285 }
286 } // namespace detail
287 
288 } // namespace kvikio
#define CUDA_DRIVER_TRY(...)
Error checking macro for CUDA driver API functions.
Definition: error.hpp:68
KvikIO namespace.
Definition: batch.hpp:27