1 /* 2 * Copyright (c) 2011-2014 Wind River Systems, Inc. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** 8 * @file 9 * @brief Debug aid 10 * 11 * 12 * The __ASSERT() macro can be used inside kernel code. 13 * 14 * Assertions are enabled by setting the __ASSERT_ON symbol to a non-zero value. 15 * There are two ways to do this: 16 * a) Use the ASSERT and ASSERT_LEVEL kconfig options 17 * b) Add "CFLAGS += -D__ASSERT_ON=<level>" at the end of a project's Makefile 18 * The Makefile method takes precedence over the kconfig option if both are 19 * used. 20 * 21 * Specifying an assertion level of 1 causes the compiler to issue warnings that 22 * the kernel contains debug-type __ASSERT() statements; this reminder is issued 23 * since assertion code is not normally present in a final product. Specifying 24 * assertion level 2 suppresses these warnings. 25 * 26 * The __ASSERT_EVAL() macro can also be used inside kernel code. 27 * 28 * It makes use of the __ASSERT() macro, but has some extra flexibility. It 29 * allows the developer to specify different actions depending whether the 30 * __ASSERT() macro is enabled or not. This can be particularly useful to 31 * prevent the compiler from generating comments (errors, warnings or remarks) 32 * about variables that are only used with __ASSERT() being assigned a value, 33 * but otherwise unused when the __ASSERT() macro is disabled. 34 * 35 * Consider the following example: 36 * 37 * int x; 38 * 39 * x = foo (); 40 * __ASSERT (x != 0, "foo() returned zero!"); 41 * 42 * If __ASSERT() is disabled, then 'x' is assigned a value, but never used. 43 * This type of situation can be resolved using the __ASSERT_EVAL() macro. 44 * 45 * __ASSERT_EVAL ((void) foo(), 46 * int x = foo(), 47 * x != 0, 48 * "foo() returned zero!"); 49 * 50 * The first parameter tells __ASSERT_EVAL() what to do if __ASSERT() is 51 * disabled. The second parameter tells __ASSERT_EVAL() what to do if 52 * __ASSERT() is enabled. The third and fourth parameters are the parameters 53 * it passes to __ASSERT(). 54 * 55 * The __ASSERT_NO_MSG() macro can be used to perform an assertion that reports 56 * the failed test and its location, but lacks additional debugging information 57 * provided to assist the user in diagnosing the problem; its use is 58 * discouraged. 59 */ 60 61 #ifndef ___ASSERT__H_ 62 #define ___ASSERT__H_ 63 #include <stdio.h> 64 65 #ifdef CONFIG_ASSERT 66 #ifndef __ASSERT_ON 67 #define __ASSERT_ON CONFIG_ASSERT_LEVEL 68 #endif 69 #endif 70 71 #ifdef CONFIG_FORCE_NO_ASSERT 72 #undef __ASSERT_ON 73 #define __ASSERT_ON 0 74 #endif 75 76 #if defined(CONFIG_ASSERT_VERBOSE) 77 #define __ASSERT_PRINT(fmt, ...) printk(fmt, ##__VA_ARGS__) 78 #else /* CONFIG_ASSERT_VERBOSE */ 79 #define __ASSERT_PRINT(fmt, ...) 80 #endif /* CONFIG_ASSERT_VERBOSE */ 81 82 #ifdef CONFIG_ASSERT_NO_MSG_INFO 83 #define __ASSERT_MSG_INFO(fmt, ...) 84 #else /* CONFIG_ASSERT_NO_MSG_INFO */ 85 #define __ASSERT_MSG_INFO(fmt, ...) __ASSERT_PRINT("\t" fmt "\n", ##__VA_ARGS__) 86 #endif /* CONFIG_ASSERT_NO_MSG_INFO */ 87 88 #if !defined(CONFIG_ASSERT_NO_COND_INFO) && !defined(CONFIG_ASSERT_NO_FILE_INFO) 89 #define __ASSERT_LOC(test) \ 90 __ASSERT_PRINT("ASSERTION FAIL [%s] @ %s:%d\n", \ 91 Z_STRINGIFY(test), \ 92 __FILE__, __LINE__) 93 #endif 94 95 #if defined(CONFIG_ASSERT_NO_COND_INFO) && !defined(CONFIG_ASSERT_NO_FILE_INFO) 96 #define __ASSERT_LOC(test) \ 97 __ASSERT_PRINT("ASSERTION FAIL @ %s:%d\n", \ 98 __FILE__, __LINE__) 99 #endif 100 101 #if !defined(CONFIG_ASSERT_NO_COND_INFO) && defined(CONFIG_ASSERT_NO_FILE_INFO) 102 #define __ASSERT_LOC(test) \ 103 __ASSERT_PRINT("ASSERTION FAIL [%s]\n", \ 104 Z_STRINGIFY(test)) 105 #endif 106 107 #if defined(CONFIG_ASSERT_NO_COND_INFO) && defined(CONFIG_ASSERT_NO_FILE_INFO) 108 #define __ASSERT_LOC(test) \ 109 __ASSERT_PRINT("ASSERTION FAIL\n") 110 #endif 111 112 #ifdef __ASSERT_ON 113 #if (__ASSERT_ON < 0) || (__ASSERT_ON > 2) 114 #error "Invalid __ASSERT() level: must be between 0 and 2" 115 #endif 116 117 #if __ASSERT_ON 118 #include <misc/printk.h> 119 120 #ifdef __cplusplus 121 extern "C" { 122 #endif 123 124 #ifdef CONFIG_ASSERT_NO_FILE_INFO 125 void assert_post_action(void); 126 #define __ASSERT_POST_ACTION() assert_post_action() 127 #else /* CONFIG_ASSERT_NO_FILE_INFO */ 128 void assert_post_action(const char *file, unsigned int line); 129 #define __ASSERT_POST_ACTION() assert_post_action(__FILE__, __LINE__) 130 #endif /* CONFIG_ASSERT_NO_FILE_INFO */ 131 132 #ifdef __cplusplus 133 } 134 #endif 135 136 #define __ASSERT_NO_MSG(test) \ 137 do { \ 138 if (!(test)) { \ 139 __ASSERT_LOC(test); \ 140 __ASSERT_POST_ACTION(); \ 141 } \ 142 } while (false) 143 144 #define __ASSERT(test, fmt, ...) \ 145 do { \ 146 if (!(test)) { \ 147 __ASSERT_LOC(test); \ 148 __ASSERT_MSG_INFO(fmt, ##__VA_ARGS__); \ 149 __ASSERT_POST_ACTION(); \ 150 } \ 151 } while (false) 152 153 #define __ASSERT_EVAL(expr1, expr2, test, fmt, ...) \ 154 do { \ 155 expr2; \ 156 __ASSERT(test, fmt, ##__VA_ARGS__); \ 157 } while (0) 158 159 #if (__ASSERT_ON == 1) 160 #warning "__ASSERT() statements are ENABLED" 161 #endif 162 #else 163 #define __ASSERT(test, fmt, ...) { } 164 #define __ASSERT_EVAL(expr1, expr2, test, fmt, ...) expr1 165 #define __ASSERT_NO_MSG(test) { } 166 #endif 167 #else 168 #define __ASSERT(test, fmt, ...) { } 169 #define __ASSERT_EVAL(expr1, expr2, test, fmt, ...) expr1 170 #define __ASSERT_NO_MSG(test) { } 171 #endif 172 173 #endif /* ZEPHYR_INCLUDE_SYS___ASSERT_H_ */ 174