1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2015-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 /** 25 * @file 26 * @brief Utility assertion macros 27 * 28 * @see "NV_ASSERT" confluence page for additional documentation 29 */ 30 31 #ifndef _NV_UTILS_ASSERT_H_ 32 #define _NV_UTILS_ASSERT_H_ 33 34 #ifdef __cplusplus 35 extern "C" { 36 #endif 37 38 /** 39 * @defgroup NV_UTILS_ASSERT Utility Assertion Macros 40 * 41 * @brief Provides a light abstraction layer for common assert macro patterns. 42 * 43 * NvPort and NvPrintf are used for debug and logging primitives. 44 * If an environment cannot use these directly then it can override 45 * the NV_PORT_HEADER and NV_PRINTF_HEADER defines in its makefile 46 * to point to appropriate replacements. 47 * @{ 48 */ 49 #include "nvstatus.h" 50 #include "nvmacro.h" 51 52 // Include portability header, falling back to NvPort if not provided. 53 #ifndef NV_PORT_HEADER 54 #define NV_PORT_HEADER "nvport/nvport.h" 55 #endif 56 #include NV_PORT_HEADER 57 58 // Include printf header, falling back to NvPrintf if not provided. 59 #ifndef NV_PRINTF_HEADER 60 #define NV_PRINTF_HEADER "utils/nvprintf.h" 61 #endif 62 #include NV_PRINTF_HEADER 63 64 /* 65 * Use __builtin_expect to improve branch predictions on the GNU compiler. 66 * 67 * Note that these macros convert the parameter to bool. They should 68 * only be used in 'if' statements. 69 * 70 * '!= 0' is used (instead of a cast to NvBool or !!) to avoid 'will always 71 * evaluate as 'true'' warnings in some gcc versions. 72 */ 73 #if defined(__GNUC__) && __GNUC__ >= 3 74 #define NV_LIKELY(expr) __builtin_expect(((expr) != 0), 1) 75 #define NV_UNLIKELY(expr) __builtin_expect(((expr) != 0), 0) 76 #else 77 #define NV_LIKELY(expr) ((expr) != 0) 78 #define NV_UNLIKELY(expr) ((expr) != 0) 79 #endif 80 81 /* 82 * Set this to pass expression, function name, file name, and line number 83 * to the nvAssertFailed functions. 84 * 85 * NOTE: NV_PRINTF_STRINGS_ALLOWED defaults to: 86 * defined(DEBUG) || defined(NV_MODS) || defined(QA_BUILD) 87 * 88 * RM_ASSERT used this condition to decide whether to print assert strings: 89 * defined(DEBUG) || defined(ASSERT_BUILD) || defined(QA_BUILD) 90 */ 91 #if !defined(NV_ASSERT_FAILED_USES_STRINGS) 92 #if (NV_PRINTF_STRINGS_ALLOWED && (defined(DEBUG) || defined(ASSERT_BUILD) || defined(QA_BUILD))) 93 #define NV_ASSERT_FAILED_USES_STRINGS 1 94 #else 95 #define NV_ASSERT_FAILED_USES_STRINGS 0 96 #endif 97 #endif 98 99 // Hook NV_ASSERT into RCDB. 100 #if !defined(NV_JOURNAL_ASSERT_ENABLE) 101 #if defined(NVRM) && (NVOS_IS_WINDOWS || NVOS_IS_UNIX || NVOS_IS_LIBOS) && !defined(NVWATCH) && !defined(NV_MODS) 102 #define NV_JOURNAL_ASSERT_ENABLE 1 103 #else 104 #define NV_JOURNAL_ASSERT_ENABLE 0 105 #endif 106 #endif 107 108 #if !defined(COVERITY_ASSERT_FAIL) 109 #if defined(__COVERITY__) 110 void __coverity_panic__(void); 111 #define COVERITY_ASSERT_FAIL() __coverity_panic__() 112 #else // defined(__COVERITY__) 113 #define COVERITY_ASSERT_FAIL() ((void) 0) 114 #endif // defined(__COVERITY__) 115 #endif // !defined(COVERITY_ASSERT_FAIL) 116 117 /* 118 * NV_ASSERT_FAILED, NV_ASSERT_OK_FAILED, NV_CHECK_FAILED, and NV_CHECK_OK_FAILED 119 * These macros are defined in three flavors: 120 * 121 * normal - expr/file/line are concatenated with format string for NVLOG. 122 * expr/file/line are passed in as parameters to a helper function 123 * for NV_PRINTF. 124 * 125 * normal for GSP-RM - expr/file/line are omitted, since each NV_PRINTF line 126 * already has them. NVLOG is not used. 127 * 128 * _FUNC - expr/file/line are passed in as parameters to a helper function 129 * for both NVLOG and NV_PRINTF. 130 * The _FUNC macros are used for pre-compiled headers on most platforms. 131 */ 132 #if defined(GSP_PLUGIN_BUILD) || (defined(NVRM) && NVOS_IS_LIBOS) 133 134 void nvAssertInit(void); 135 void nvAssertDestroy(void); 136 137 #if NV_JOURNAL_ASSERT_ENABLE 138 void nvAssertFailed(void); 139 void nvAssertOkFailed(NvU32 status); 140 #else 141 #define nvAssertFailed(...) 142 #define nvAssertOkFailed(...) 143 #endif 144 145 #define NV_ASSERT_FAILED(exprStr) \ 146 do { \ 147 NV_LOG_SPECIAL(LEVEL_ERROR, RM_GSP_LOG_SPECIAL_ASSERT_FAILED, \ 148 exprStr "\n"); \ 149 nvAssertFailed(); \ 150 COVERITY_ASSERT_FAIL(); \ 151 PORT_BREAKPOINT(); \ 152 } while(0) 153 154 #define NV_ASSERT_OK_FAILED(exprStr, status) \ 155 do { \ 156 NV_LOG_SPECIAL(LEVEL_ERROR, RM_GSP_LOG_SPECIAL_ASSERT_OK_FAILED, \ 157 exprStr "\n", status); \ 158 nvAssertOkFailed(status); \ 159 COVERITY_ASSERT_FAIL(); \ 160 PORT_BREAKPOINT(); \ 161 } while(0) 162 163 #define NV_CHECK_FAILED(level, exprStr) \ 164 do { \ 165 NV_LOG_SPECIAL(level, RM_GSP_LOG_SPECIAL_CHECK_FAILED, \ 166 exprStr "\n"); \ 167 } while(0) \ 168 169 #define NV_CHECK_OK_FAILED(level, exprStr, status) \ 170 do { \ 171 NV_LOG_SPECIAL(level, RM_GSP_LOG_SPECIAL_CHECK_OK_FAILED, \ 172 exprStr "\n", status); \ 173 } while (0) 174 175 #else // defined(GSP_PLUGIN_BUILD) || (defined(NVRM) && NVOS_IS_LIBOS) 176 177 #if NV_ASSERT_FAILED_USES_STRINGS 178 #define NV_ASSERT_FAILED_FUNC_COMMA_PARAM(exprStr) , exprStr, __FILE__, __LINE__ 179 #define NV_ASSERT_FAILED_FUNC_PARAM(exprStr) exprStr, __FILE__, __LINE__ 180 #define NV_ASSERT_FAILED_FUNC_COMMA_TYPE ,const char *pszExpr, const char *pszFileName, NvU32 lineNum 181 #define NV_ASSERT_FAILED_FUNC_TYPE const char *pszExpr, const char *pszFileName, NvU32 lineNum 182 #else 183 #define NV_ASSERT_FAILED_FUNC_COMMA_PARAM(exprStr) , __LINE__ 184 #define NV_ASSERT_FAILED_FUNC_PARAM(exprStr) __LINE__ 185 #define NV_ASSERT_FAILED_FUNC_COMMA_TYPE , NvU32 lineNum 186 #define NV_ASSERT_FAILED_FUNC_TYPE NvU32 lineNum 187 #endif 188 189 void nvAssertInit(void); 190 void nvAssertDestroy(void); 191 192 // Helper function prototypes for _FAILED macros below. 193 #if NV_PRINTF_ENABLED || NV_JOURNAL_ASSERT_ENABLE 194 void nvAssertFailed(NV_ASSERT_FAILED_FUNC_TYPE); 195 void nvAssertOkFailed(NvU32 status NV_ASSERT_FAILED_FUNC_COMMA_TYPE); 196 void nvCheckFailed(NvU32 level NV_ASSERT_FAILED_FUNC_COMMA_TYPE); 197 void nvCheckOkFailed(NvU32 level, NvU32 status NV_ASSERT_FAILED_FUNC_COMMA_TYPE); 198 void nvAssertFailedNoLog(NV_ASSERT_FAILED_FUNC_TYPE); 199 void nvAssertOkFailedNoLog(NvU32 status NV_ASSERT_FAILED_FUNC_COMMA_TYPE); 200 void nvCheckFailedNoLog(NvU32 level NV_ASSERT_FAILED_FUNC_COMMA_TYPE); 201 void nvCheckOkFailedNoLog(NvU32 level, NvU32 status NV_ASSERT_FAILED_FUNC_COMMA_TYPE); 202 #else // NV_PRINTF_ENABLED || NV_JOURNAL_ASSERT_ENABLE 203 #define nvAssertFailed(...) 204 #define nvAssertOkFailed(...) 205 #define nvCheckFailed(...) 206 #define nvCheckOkFailed(...) 207 #define nvAssertFailedNoLog(...) 208 #define nvAssertOkFailedNoLog(...) 209 #define nvCheckFailedNoLog(...) 210 #define nvCheckOkFailedNoLog(...) 211 #endif // NV_PRINTF_ENABLED || NV_JOURNAL_ASSERT_ENABLE 212 213 #define NV_ASSERT_LOG(level, fmt, ...) \ 214 NVLOG_PRINTF(NV_PRINTF_MODULE, NVLOG_ROUTE_RM, level, \ 215 NV_PRINTF_ADD_PREFIX(fmt), ##__VA_ARGS__) 216 217 #define NV_ASSERT_FAILED(exprStr) \ 218 do { \ 219 NV_ASSERT_LOG(LEVEL_ERROR, "Assertion failed: " exprStr); \ 220 nvAssertFailedNoLog(NV_ASSERT_FAILED_FUNC_PARAM(exprStr)); \ 221 COVERITY_ASSERT_FAIL(); \ 222 PORT_BREAKPOINT_CHECKED(); \ 223 } while(0) 224 225 #define NV_ASSERT_OK_FAILED(exprStr, status) \ 226 do { \ 227 NV_ASSERT_LOG(LEVEL_ERROR, "Assertion failed: 0x%08X returned from " \ 228 exprStr, status); \ 229 nvAssertOkFailedNoLog(status \ 230 NV_ASSERT_FAILED_FUNC_COMMA_PARAM(exprStr)); \ 231 COVERITY_ASSERT_FAIL(); \ 232 PORT_BREAKPOINT_CHECKED(); \ 233 } while(0) 234 235 #define NV_CHECK_FAILED(level, exprStr) \ 236 do { \ 237 NV_ASSERT_LOG(level, "Check failed: " exprStr); \ 238 if (NV_PRINTF_LEVEL_ENABLED(level)) \ 239 { \ 240 nvCheckFailedNoLog(level \ 241 NV_ASSERT_FAILED_FUNC_COMMA_PARAM(exprStr)); \ 242 } \ 243 } while(0) 244 245 #define NV_CHECK_OK_FAILED(level, exprStr, status) \ 246 do { \ 247 NV_ASSERT_LOG(level, "Check failed: 0x%08X returned from " \ 248 exprStr, status); \ 249 if (NV_PRINTF_LEVEL_ENABLED(level)) \ 250 { \ 251 nvCheckOkFailedNoLog(level, status \ 252 NV_ASSERT_FAILED_FUNC_COMMA_PARAM(exprStr)); \ 253 } \ 254 } while(0) 255 256 #define NV_ASSERT_FAILED_FUNC(exprStr) \ 257 do { \ 258 nvAssertFailed(NV_ASSERT_FAILED_FUNC_PARAM(exprStr)); \ 259 COVERITY_ASSERT_FAIL(); \ 260 PORT_BREAKPOINT_CHECKED(); \ 261 } while(0) 262 263 #define NV_ASSERT_OK_FAILED_FUNC(exprStr, status) \ 264 do { \ 265 nvAssertOkFail(status NV_ASSERT_FAILED_FUNC_COMMA_PARAM(exprStr)); \ 266 COVERITY_ASSERT_FAIL(); \ 267 PORT_BREAKPOINT_CHECKED(); \ 268 } while(0) 269 270 #define NV_CHECK_FAILED_FUNC(level, exprStr) \ 271 if (NV_PRINTF_LEVEL_ENABLED(level)) \ 272 { \ 273 nvCheckFailed(level NV_ASSERT_FAILED_FUNC_COMMA_PARAM(exprStr)) \ 274 } 275 276 #define NV_CHECK_OK_FAILED_FUNC(level, exprStr, status) \ 277 if (NV_PRINTF_LEVEL_ENABLED(level)) \ 278 { \ 279 nvCheckOkFailed(level, status \ 280 NV_ASSERT_FAILED_FUNC_COMMA_PARAM(exprStr)) \ 281 } 282 283 #endif // defined(GSP_PLUGIN_BUILD) || (defined(NVRM) && NVOS_IS_LIBOS) 284 285 /* 286 * Defines for precompiled headers. 287 * 288 * On platforms other than GSP-RM, the _INLINE macros cannot be used inside 289 * precompiled headers due to conflicting NVLOG_PRINT_IDs. 290 */ 291 #if defined(GSP_PLUGIN_BUILD) || (defined(NVRM) && NVOS_IS_LIBOS) 292 #define NV_ASSERT_FAILED_PRECOMP NV_ASSERT_FAILED 293 #else 294 #define NV_ASSERT_FAILED_PRECOMP NV_ASSERT_FAILED_FUNC 295 #endif 296 297 // ***************************************************************************** 298 // * NV_ASSERT family of macros * 299 // ***************************************************************************** 300 /** 301 * General notes: 302 * 303 * Assert that an expression is true. If not, do the actions defined 304 * in NV_ASSERT_FAILED as well as an "other action": 305 * Print an error message in the debug output 306 * Log an error message in NvLog 307 * Mark as an error condition for coverity 308 * Breakpoint 309 * Log an assert record to the journal 310 * "Other action" as defined by each macro below. 311 * 312 * The actions are enabled or omitted based on platform and build, and the 313 * implementations are platform dependent. 314 * 315 * The expression is always evaluated even if assertion failures are not logged 316 * in the environment. Use @ref NV_ASSERT_CHECKED if the expression should only 317 * be evaluated in checked builds. 318 * 319 * USE GENEROUSLY FOR any condition that requires immediate action from NVIDIA. 320 * Expect to be ARBed on bugs when an assert you added shows up internally 321 * or in the field. 322 * 323 * DO NOT USE for normal run-time conditions, such as a user application 324 * passing a bad parameter. 325 */ 326 327 /** 328 * Assert that an expression is true. 329 * 330 * @param[in] expr Expression that evaluates to a truth value. 331 */ 332 #define NV_ASSERT(expr) \ 333 NV_ASSERT_OR_ELSE_STR(expr, #expr, /* no other action */) 334 335 /** 336 * Assert that an expression is true only in checked builds. 337 * 338 * @note The expression is only evaluated in checked builds so should 339 * not contain required side-effects. 340 * Also to prevent side effects, no "other action" is permitted. 341 * 342 * @param[in] expr Expression that evaluates to a truth value. 343 */ 344 #if PORT_IS_CHECKED_BUILD 345 #define NV_ASSERT_CHECKED(expr) \ 346 NV_ASSERT_OR_ELSE_STR(expr, #expr, /* no other action */) 347 #define NV_ASSERT_CHECKED_PRECOMP(expr) \ 348 NV_ASSERT_OR_ELSE_STR_PRECOMP(expr, #expr, /* no other action */) 349 #else 350 #define NV_ASSERT_CHECKED(expr) ((void)0) 351 #define NV_ASSERT_CHECKED_PRECOMP(expr) ((void)0) 352 #endif 353 354 /** 355 * Assert that an expression is true or else do something. 356 * 357 * This macro can't use NV_ASSERT_OR_ELSE_STR when NV_PRINTF is passed in as 358 * the elseStmt parameter. 359 * 360 * @param[in] expr Expression that evaluates to a truth value. 361 * @param[in] elseStmt Statement to evaluate if the expression is false. 362 */ 363 #define NV_ASSERT_OR_ELSE(expr, elseStmt) \ 364 if (1) \ 365 { \ 366 PORT_COVERAGE_PUSH_OFF(); \ 367 if (NV_UNLIKELY(!(expr))) \ 368 { \ 369 NV_ASSERT_FAILED(#expr); \ 370 elseStmt; \ 371 } \ 372 PORT_COVERAGE_POP(); \ 373 } else ((void) 0) 374 375 /** 376 * Assert that an expression is true or else goto a label. 377 * 378 * @param[in] expr Expression that evaluates to a truth value. 379 * @param[in] label Label to jump to when the expression is false. 380 */ 381 #define NV_ASSERT_OR_GOTO(expr, label) \ 382 NV_ASSERT_OR_ELSE_STR(expr, #expr, goto label) 383 384 /** 385 * Assert that an expression is true or else return a value. 386 * 387 * @param[in] expr Expression that evaluates to a truth value. 388 * @param[in] retval Value to return if the expression is false. 389 */ 390 #define NV_ASSERT_OR_RETURN(expr, retval) \ 391 NV_ASSERT_OR_ELSE_STR(expr, #expr, return (retval)) 392 393 /** 394 * Assert that an expression is true or else return void. 395 * 396 * @param[in] expr Expression that evaluates to a truth value. 397 */ 398 #define NV_ASSERT_OR_RETURN_VOID(expr) \ 399 NV_ASSERT_OR_ELSE_STR(expr, #expr, return) 400 401 /** 402 * Assert that an expression is true or else do something. 403 * 404 * Although it can be used directly, this second level macro is designed to be 405 * called from other macros. Passing expr through multiple levels of macros 406 * before it is stringified expands it. This is especially bad for DRF macros, 407 * which result in an embedded %, breaking the format string in the 408 * NV_ASSERT_FAILED_INLINE macro defined above. The macros in this header 409 * always pass the stringified expr as a into the second level macros as 410 * a separate parameter. 411 * 412 * @param[in] expr Expression that evaluates to a truth value. 413 * @param[in] exprStr Expression as a string. 414 * @param[in] elseStmt Statement to evaluate if the expression is false. 415 */ 416 #define NV_ASSERT_OR_ELSE_STR(expr, exprStr, elseStmt) \ 417 do \ 418 { \ 419 PORT_COVERAGE_PUSH_OFF(); \ 420 if (NV_UNLIKELY(!(expr))) \ 421 { \ 422 NV_ASSERT_FAILED(exprStr); \ 423 elseStmt; \ 424 } \ 425 PORT_COVERAGE_POP(); \ 426 } while (0) 427 428 // ***************************************************************************** 429 // * NV_ASSERT_OK family of macros * 430 // ***************************************************************************** 431 /** 432 * General notes: 433 * 434 * Assert that an expression evaluates to NV_OK. If not, do the actions defined 435 * in NV_ASSERT_OK_FAILED as well as an "other action": 436 * Print an error message in the debug output, including decoded NV_STATUS. 437 * Log an error message in NvLog. 438 * Mark as an error condition for coverity. 439 * Breakpoint. 440 * Log an assert record to the journal. 441 * "Other action" as defined by each macro below. 442 * 443 * The actions are enabled or omitted based on platform and build, and the 444 * implementations are platform dependent. 445 * 446 * The expression is always evaluated even if assertion failures are not logged 447 * in the environment. Use @ref NV_ASSERT_OK_CHECKED if the expression should 448 * only be evaluated in checked builds. 449 * 450 * USE GENEROUSLY FOR any condition that requires immediate action from NVIDIA. 451 * Expect to be ARBed on bugs when an assert you added shows up internally 452 * or in the field. 453 * 454 * DO NOT USE for normal run-time conditions, such as a user application 455 * passing a bad parameter. 456 */ 457 458 /** 459 * Assert that an expression evaluates to NV_OK. 460 * 461 * @param[in] expr Expression that evaluates to an NV_STATUS. 462 */ 463 #define NV_ASSERT_OK(expr) \ 464 do \ 465 { \ 466 NV_STATUS rm_pvt_status; \ 467 NV_ASSERT_OK_OR_ELSE_STR(rm_pvt_status, expr, #expr, \ 468 /* no other action */); \ 469 } while(0) 470 471 /** 472 * Assert that an expression evaluates to NV_OK only in checked builds. 473 * 474 * @note The expression is only evaluated in checked builds so should 475 * not contain required side-effects. 476 * Also to prevent side effects, no "other action" is permitted, 477 * and the status parameter is omitted. 478 * 479 * @param[in] expr Expression that evaluates to an NV_STATUS. 480 */ 481 #if PORT_IS_CHECKED_BUILD 482 #define NV_ASSERT_OK_CHECKED(expr) \ 483 do \ 484 { \ 485 NV_STATUS rm_pvt_status; \ 486 NV_ASSERT_OK_OR_ELSE_STR(rm_pvt_status, expr, #expr, \ 487 return rm_pvt_status); \ 488 } while(0) 489 #else 490 #define NV_ASSERT_OK_CHECKED(expr) ((void)0) 491 #endif 492 493 /*! 494 * Call a function that returns NV_STATUS and assert that the 495 * return values is NV_OK. In case this was a first failure 496 * update global status @ref status. 497 * 498 * @param[in] status The NV_STATUS variable to capture the status 499 * @param[in] expr Expression that evaluates to an NV_STATUS. 500 */ 501 #define NV_ASSERT_OK_OR_CAPTURE_FIRST_ERROR(status, expr) \ 502 do \ 503 { \ 504 NV_STATUS rm_pvt_status; \ 505 NV_ASSERT_OK_OR_ELSE_STR(rm_pvt_status, expr, #expr, \ 506 if (status == NV_OK) status = rm_pvt_status); \ 507 } while (0) 508 509 /** 510 * Assert that an expression evaluates to NV_OK or else do something. 511 * 512 * This macro can't use NV_ASSERT_OK_OR_ELSE_STR when NV_PRINTF is passed in as 513 * the elseStmt parameter. 514 * 515 * @param[in] status The NV_STATUS variable to capture the status 516 * @param[in] expr Expression that evaluates to an NV_STATUS. 517 * @param[in] elseStmt Statement to evaluate if the expression is false. 518 */ 519 #define NV_ASSERT_OK_OR_ELSE(status, expr, elseStmt) \ 520 do \ 521 { \ 522 status = (expr); \ 523 PORT_COVERAGE_PUSH_OFF(); \ 524 if (NV_UNLIKELY(NV_OK != status)) \ 525 { \ 526 NV_ASSERT_OK_FAILED(#expr, status); \ 527 elseStmt; \ 528 } \ 529 PORT_COVERAGE_POP(); \ 530 } while(0) 531 532 /** 533 * Assert that an expression evaluates to NV_OK or else goto a label. 534 * 535 * @param[in] status The NV_STATUS variable to capture the status 536 * @param[in] expr Expression that evaluates to an NV_STATUS. 537 * @param[in] label Label to jump to when the expression is false. 538 */ 539 #define NV_ASSERT_OK_OR_GOTO(status, expr, label) \ 540 NV_ASSERT_OK_OR_ELSE_STR(status, expr, #expr, goto label); 541 542 /** 543 * Assert that an expression evaluates to NV_TRUE or else goto a label. 544 * 545 * @param[in] status The NV_STATUS variable to capture the status 546 * @param[in] cond Condition that evaluates to either NV_TRUE or NV_FALSE. 547 * @param[in] error Error to be reflected in @ref status when @cond evaluates 548 to NV_FALSE. 549 * @param[in] label Label to jump to when @ref cond evaluates to NV_FALSE. 550 */ 551 #define NV_ASSERT_TRUE_OR_GOTO(status, cond, error, label) \ 552 NV_ASSERT_OK_OR_ELSE_STR(status, ((cond) ? NV_OK : (error)), \ 553 #cond, goto label); 554 555 /** 556 * Assert that an expression evaluates to NV_OK or else return the status. 557 * 558 * @param[in] expr Expression that evaluates to an NV_STATUS. 559 */ 560 #define NV_ASSERT_OK_OR_RETURN(expr) \ 561 do \ 562 { \ 563 NV_STATUS rm_pvt_status; \ 564 NV_ASSERT_OK_OR_ELSE_STR(rm_pvt_status, expr, #expr, \ 565 return rm_pvt_status); \ 566 } while(0) 567 568 /** 569 * Assert that an expression evaluates to NV_OK or else do something. 570 * 571 * Although it can be used directly, this second level macro is designed to be 572 * called from other macros. Passing expr through multiple levels of macros 573 * before it is stringified expands it. This is especially bad for DRF macros, 574 * which result in an embedded %, breaking the format string in the 575 * NV_ASSERT_OK_FAILED_INLINE macro defined above. The macros in this header 576 * always pass the stringified expr as a into the second level macros as 577 * a separate parameter. 578 * 579 * @param[in] status The NV_STATUS variable to capture the status 580 * @param[in] expr Expression that evaluates to an NV_STATUS. 581 * @param[in] exprStr Expression as a string. 582 * @param[in] elseStmt Statement to evaluate if the expression is false. 583 */ 584 #define NV_ASSERT_OK_OR_ELSE_STR(status, expr, exprStr, elseStmt) \ 585 do \ 586 { \ 587 status = (expr); \ 588 PORT_COVERAGE_PUSH_OFF(); \ 589 if (NV_UNLIKELY(NV_OK != status)) \ 590 { \ 591 NV_ASSERT_OK_FAILED(exprStr, status); \ 592 elseStmt; \ 593 } \ 594 PORT_COVERAGE_POP(); \ 595 } while(0) 596 597 // ***************************************************************************** 598 // * NV_CHECK family of macros * 599 // ***************************************************************************** 600 /** 601 * General notes: 602 * 603 * Check that an expression is true. If not, do the following actions: 604 * Print a message in the debug output at user specified level. 605 * Log a message in NvLog at user specified level. 606 * "Other action" as defined by each macro below. 607 * 608 * The actions are enabled or omitted based on platform and build, and the 609 * implementations are platform dependent. 610 * 611 * The expression is always evaluated even if check failures are not logged 612 * in the environment. Use @ref NV_CHECK_CHECKED if the expression should only 613 * be evaluated in checked builds. 614 * 615 * USE FOR error conditions that DO NOT require immediate action from NVIDIA, 616 * but may be useful in diagnosing other issues. 617 */ 618 619 /** 620 * Check that an expression is true. 621 * 622 * @param[in] level NV_PRINTF LEVEL to print at 623 * @param[in] expr Expression that evaluates to a truth value. 624 */ 625 #define NV_CHECK(level, expr) \ 626 NV_CHECK_OR_ELSE_STR(level, expr, #expr, /* no other action */) 627 628 /** 629 * Check that an expression is true only in checked builds. 630 * 631 * @note The expression is only evaluated in checked builds so should 632 * not contain required side-effects. 633 * Also to prevent side effects, no "other action" is permitted. 634 * 635 * @param[in] level NV_PRINTF LEVEL to print at 636 * @param[in] expr Expression that evaluates to a truth value. 637 */ 638 #if PORT_IS_CHECKED_BUILD 639 #define NV_CHECK_CHECKED(level, expr) \ 640 NV_CHECK_OR_ELSE_STR(level, expr, #expr, /* no other action */) 641 #else 642 #define NV_CHECK_CHECKED(level, expr) ((void)0) 643 #endif 644 645 /** 646 * Check that an expression is true or else do something. 647 * 648 * This macro can't use NV_CHECK_OR_ELSE_STR when NV_PRINTF is passed in as 649 * the elseStmt parameter. 650 * 651 * @param[in] level NV_PRINTF LEVEL to print at 652 * @param[in] expr Expression that evaluates to a truth value. 653 * @param[in] elseStmt Statement to evaluate if the expression is false. 654 */ 655 #define NV_CHECK_OR_ELSE(level, expr, elseStmt) \ 656 do \ 657 { \ 658 if (NV_UNLIKELY(!(expr))) \ 659 { \ 660 NV_CHECK_FAILED(level, #expr); \ 661 elseStmt; \ 662 } \ 663 } while (0) 664 665 /** 666 * Check that an expression is true or else goto a label. 667 * 668 * @param[in] level NV_PRINTF LEVEL to print at 669 * @param[in] expr Expression that evaluates to a truth value. 670 * @param[in] label Label to jump to when the expression is false. 671 */ 672 #define NV_CHECK_OR_GOTO(level, expr, label) \ 673 NV_CHECK_OR_ELSE_STR(level, expr, #expr, goto label) 674 675 /** 676 * Check that an expression is true or else return a value. 677 * 678 * @param[in] level NV_PRINTF LEVEL to print at 679 * @param[in] expr Expression that evaluates to a truth value. 680 * @param[in] retval Value to return if the expression is false. 681 */ 682 #define NV_CHECK_OR_RETURN(level, expr, retval) \ 683 NV_CHECK_OR_ELSE_STR(level, expr, #expr, return (retval)) 684 685 /** 686 * Check that an expression is true or else return void. 687 * 688 * @param[in] level NV_PRINTF LEVEL to print at 689 * @param[in] expr Expression that evaluates to a truth value. 690 */ 691 #define NV_CHECK_OR_RETURN_VOID(level, expr) \ 692 NV_CHECK_OR_ELSE_STR(level, expr, #expr, return) 693 694 /** 695 * Check that an expression is true or else do something. 696 * 697 * Although it can be used directly, this second level macro is designed to be 698 * called from other macros. Passing expr through multiple levels of macros 699 * before it is stringified expands it. This is especially bad for DRF macros, 700 * which result in an embedded %, breaking the format string in the 701 * NV_CHECK_FAILED_INLINE macro defined above. The macros in this header 702 * always pass the stringified expr as a into the second level macros as 703 * a separate parameter. 704 * 705 * @param[in] level NV_PRINTF LEVEL to print at 706 * @param[in] expr Expression that evaluates to a truth value. 707 * @param[in] exprStr Expression as a string. 708 * @param[in] elseStmt Statement to evaluate if the expression is false. 709 */ 710 #define NV_CHECK_OR_ELSE_STR(level, expr, exprStr, elseStmt) \ 711 do \ 712 { \ 713 if (NV_UNLIKELY(!(expr))) \ 714 { \ 715 NV_CHECK_FAILED(level, exprStr); \ 716 elseStmt; \ 717 } \ 718 } while (0) 719 720 721 // ***************************************************************************** 722 // * NV_CHECK_OK family of macros * 723 // ***************************************************************************** 724 /** 725 * General notes: 726 * 727 * Check that an expression evaluates to NV_OK. If not, do the following actions: 728 * Print a message in the debug output at user specified. 729 * Log a message in NvLog at user specified level. 730 * "Other action" as defined by each macro below. 731 * 732 * The actions are enabled or omitted based on platform and build, and the 733 * implementations are platform dependent. 734 * 735 * The expression is always evaluated even if assertion failures are not logged 736 * in the environment. Use @ref NV_ASSERT_OK_CHECKED if the expression should 737 * only be evaluated in checked builds. 738 * 739 * USE FOR error conditions that DO NOT require immediate action from NVIDIA, 740 * but may be useful in diagnosing other issues. 741 */ 742 743 /** 744 * Check that an expression evaluates to NV_OK. 745 * 746 * @param[in] status The NV_STATUS variable to capture the status 747 * @param[in] level NV_PRINTF LEVEL to print at 748 * @param[in] expr Expression that evaluates to an NV_STATUS. 749 */ 750 #define NV_CHECK_OK(status, level, expr) \ 751 do \ 752 { \ 753 NV_CHECK_OK_OR_ELSE_STR(status, level, expr, #expr, \ 754 /* no other action */); \ 755 } while(0) 756 757 /** 758 * Check that an expression evaluates to NV_OK only in checked builds. 759 * 760 * @note The expression is only evaluated in checked builds so should 761 * not contain required side-effects. 762 * Also to prevent side effects, no "other action" is permitted, 763 * and the status parameter is omitted. 764 * 765 * @param[in] level NV_PRINTF LEVEL to print at 766 * @param[in] expr Expression that evaluates to an NV_STATUS. 767 */ 768 #if PORT_IS_CHECKED_BUILD 769 #define NV_CHECK_OK_CHECKED(level, expr) \ 770 do \ 771 { \ 772 NV_STATUS rm_pvt_status; \ 773 NV_CHECK_OK_OR_ELSE_STR(rm_pvt_status, level, expr, #expr, \ 774 /* no other action */); \ 775 } while(0) 776 #else 777 #define NV_CHECK_OK_CHECKED(level, expr) ((void)0) 778 #endif 779 780 /*! 781 * Call a function that returns NV_STATUS and check that the return values is 782 * NV_OK. If an error is returned, record the error code. In case this was a 783 * first failure update global status @ref status. 784 * 785 * @param[in] status The NV_STATUS variable to capture the status 786 * @param[in] level NV_PRINTF LEVEL to print at 787 * @param[in] expr Expression that evaluates to an NV_STATUS. 788 */ 789 #define NV_CHECK_OK_OR_CAPTURE_FIRST_ERROR(status, level, expr) \ 790 do \ 791 { \ 792 NV_STATUS rm_pvt_status; \ 793 NV_CHECK_OK_OR_ELSE_STR(rm_pvt_status, level, expr, #expr, \ 794 if (status == NV_OK) status = rm_pvt_status); \ 795 } while (0) 796 797 /** 798 * Check that an expression evaluates to NV_OK or else do something. 799 * 800 * This macro can't use NV_CHECK_OK_OR_ELSE_STR when NV_PRINTF is passed in as 801 * the elseStmt parameter. 802 * 803 * @param[in] status The NV_STATUS variable to capture the status 804 * @param[in] level NV_PRINTF LEVEL to print at 805 * @param[in] expr Expression that evaluates to an NV_STATUS. 806 * @param[in] elseStmt Statement to evaluate if the expression returns error. 807 */ 808 #define NV_CHECK_OK_OR_ELSE(status, level, expr, elseStmt) \ 809 do \ 810 { \ 811 status = (expr); \ 812 if (NV_UNLIKELY(NV_OK != status)) \ 813 { \ 814 NV_CHECK_OK_FAILED(level, #expr, status); \ 815 elseStmt; \ 816 } \ 817 } while (0) 818 819 /** 820 * Check that an expression evaluates to NV_OK or else goto a label. 821 * 822 * @param[in] status The NV_STATUS variable to capture the status 823 * @param[in] level NV_PRINTF LEVEL to print at 824 * @param[in] expr Expression that evaluates to an NV_STATUS. 825 * @param[in] label Label to jump to when the expression returns error. 826 */ 827 #define NV_CHECK_OK_OR_GOTO(status, level, expr, label) \ 828 NV_CHECK_OK_OR_ELSE_STR(status, level, expr, #expr, goto label) 829 830 /** 831 * Check that an expression evaluates to NV_TRUE or else goto a label. 832 * 833 * @param[in] status The NV_STATUS variable to capture the status 834 * @param[in] level NV_PRINTF LEVEL to print at 835 * @param[in] expr Expression that evaluates to either NV_TRUE or NV_FALSE. 836 * @param[in] error Error to be reflected in @p status when @p expr evaluates 837 to NV_FALSE. 838 * @param[in] label Label to jump to when @p expr evaluates to NV_FALSE. 839 */ 840 #define NV_CHECK_TRUE_OR_GOTO(status, level, expr, error, label) \ 841 NV_CHECK_OK_OR_ELSE_STR(status, level, ((expr) ? NV_OK : (error)), \ 842 #expr, goto label); 843 844 /** 845 * Check that an expression evaluates to NV_OK or return the status. 846 * 847 * @param[in] level NV_PRINTF LEVEL to print at 848 * @param[in] expr Expression that evaluates to an NV_STATUS. 849 */ 850 #define NV_CHECK_OK_OR_RETURN(level, expr) \ 851 do \ 852 { \ 853 NV_STATUS rm_pvt_status; \ 854 NV_CHECK_OK_OR_ELSE_STR(rm_pvt_status, level, expr, #expr, \ 855 return rm_pvt_status); \ 856 } while(0) 857 858 859 /** 860 * Check that an expression evaluates to NV_OK or else record the error code and 861 * do something. 862 * 863 * Although it can be used directly, this second level macro is designed to be 864 * called from other macros. Passing expr through multiple levels of macros 865 * before it is stringified expands it. This is especially bad for DRF macros, 866 * which result in an embedded %, breaking the format string in the 867 * NV_CHECK_OK_FAILED_INLINE macro defined above. The macros in this header 868 * always pass the stringified expr as a into the second level macros as 869 * a separate parameter. 870 * 871 * @param[in] status The NV_STATUS variable to capture the status 872 * @param[in] level NV_PRINTF LEVEL to print at 873 * @param[in] expr Expression that evaluates to an NV_STATUS. 874 * @param[in] exprStr Expression as a string. 875 * @param[in] elseStmt Statement to evaluate if the expression returns error. 876 */ 877 #define NV_CHECK_OK_OR_ELSE_STR(status, level, expr, exprStr, elseStmt) \ 878 do \ 879 { \ 880 status = (expr); \ 881 if (NV_UNLIKELY(NV_OK != status)) \ 882 { \ 883 NV_CHECK_OK_FAILED(level, exprStr, status); \ 884 elseStmt; \ 885 } \ 886 } while (0) 887 888 889 // ***************************************************************************** 890 // * NV_ASSERT_PRECOMP family of macros * 891 // ***************************************************************************** 892 /** 893 * General notes: 894 * 895 * Exactly the same as the NV_ASSERT macros, but always safe to use in 896 * precompiled headers. 897 * 898 * On platforms other than GSP-RM, the _INLINE macros cannot be used inside 899 * precompiled headers due to conflicting NVLOG_PRINT_IDs. The PRECOMP macros 900 * work around this issue by calling helper functions for NvLog. 901 * 902 * Hoping for a better solution, only the macro variants that are currently 903 * used in precompiled headers are defined. 904 * 905 * See the NV_ASSERT documentation above for parameters and use cases. 906 */ 907 #define NV_ASSERT_PRECOMP(expr) \ 908 NV_ASSERT_OR_ELSE_STR_PRECOMP(expr, #expr, /* no other action */) 909 910 #define NV_ASSERT_OR_RETURN_PRECOMP(expr, retval) \ 911 NV_ASSERT_OR_ELSE_STR_PRECOMP(expr, #expr, return (retval)) 912 913 #define NV_ASSERT_OR_RETURN_VOID_PRECOMP(expr) \ 914 NV_ASSERT_OR_ELSE_STR_PRECOMP(expr, #expr, return) 915 916 #define NV_ASSERT_OR_ELSE_STR_PRECOMP(expr, exprStr, elseStmt) \ 917 do \ 918 { \ 919 PORT_COVERAGE_PUSH_OFF(); \ 920 if (NV_UNLIKELY(!(expr))) \ 921 { \ 922 NV_ASSERT_FAILED_PRECOMP(exprStr); \ 923 elseStmt; \ 924 } \ 925 PORT_COVERAGE_POP(); \ 926 } while (0) 927 928 /** 929 * @def NV_CHECKED_ONLY 930 * @brief Compile a piece of code only in checked builds. 931 * 932 * This macro helps avoid #ifdefs to improve readability but should be 933 * used sparingly. 934 * 935 * Cases that make heavy use of this should likely define a wrapper 936 * macro or other abstraction for the build variation. 937 * For example NV_CHECKED_ONLY(NV_PRINTF(...)) is not a good use case. 938 * 939 * A typical use case is declaring and setting a canary value: 940 * ~~~{.c} 941 * typedef struct 942 * { 943 * NV_CHECKED_ONLY(NvU32 canary); 944 * ... 945 * } MY_STRUCT; 946 * 947 * void initMyStruct(MY_STRUCT *pStruct) 948 * { 949 * NV_CHECKED_ONLY(pStruct->canaray = 0xDEADBEEF); 950 * ... 951 * } 952 * 953 * void destroyMyStruct(MY_STRUCT *pStruct) 954 * { 955 * NV_ASSERT_CHECKED(pStruct->canaray == 0xDEADBEEF); 956 * ... 957 * } 958 * ~~~ 959 */ 960 #if PORT_IS_CHECKED_BUILD 961 #define NV_CHECKED_ONLY NV_EXPAND 962 #else 963 #define NV_CHECKED_ONLY NV_DISCARD 964 #endif 965 966 // Verify prerequisites are defined. 967 #ifndef PORT_IS_CHECKED_BUILD 968 #error "NV_PORT_HEADER must define PORT_IS_CHECKED_BUILD" 969 #endif 970 #ifndef PORT_BREAKPOINT_CHECKED 971 #error "NV_PORT_HEADER must define PORT_BREAKPOINT_CHECKED" 972 #endif 973 #ifndef PORT_COVERAGE_PUSH_OFF 974 #error "NV_PORT_HEADER must define PORT_COVERAGE_PUSH_OFF" 975 #endif 976 #ifndef PORT_COVERAGE_POP 977 #error "NV_PORT_HEADER must define PORT_COVERAGE_POP" 978 #endif 979 #ifndef NV_PRINTF 980 #error "NV_PRINTF_HEADER must define NV_PRINTF" 981 #endif 982 983 984 #ifdef __cplusplus 985 } 986 #endif //__cplusplus 987 /// @} 988 #endif // _NV_UTILS_ASSERT_H_ 989