Motr  M0
assert.h
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #pragma once
24 
25 #ifndef __MOTR_LIB_ASSERT_H__
26 #define __MOTR_LIB_ASSERT_H__
27 
28 #include <stddef.h> /* NULL */
29 #include <stdarg.h> /* va_list */
30 
37 /*
38  * Kernel and ansidecl.h define GCC_VERSION in an incompatible way. Use our own
39  * definition in the ansidecl.h' format. Since Motr sources can include kernel
40  * headers after assert.h, we don't want to re-define kernel's GCC_VERSION.
41  * Therefore, name it as M0_GCC_VERSION.
42  *
43  * Trust GCC_VERSION < 10000, because it is definitely the ansidecl.h' format.
44  * We define fake GCC_VERSION for gccxml to disable _Static_assert.
45  */
46 #if defined(GCC_VERSION) && GCC_VERSION < 10000
47 #define M0_GCC_VERSION GCC_VERSION
48 #elif defined(__GNUC__) && defined(__GNUC_MINOR__)
49 #define M0_GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
50 #endif
51 
52 /* this should be defined before target-specific assert.h is included */
53 #ifdef M0_NDEBUG
54 #define M0_ASSERT_OFF (1)
55 #else
56 #define M0_ASSERT_OFF (0)
57 #endif
58 
59 #ifdef ENABLE_EXPENSIVE_CHECKS
60 #define M0_ASSERT_EX_ON (1)
61 #else
62 #define M0_ASSERT_EX_ON (0)
63 #endif
64 
65 /*
66  * likely() and unlikely() are defined here rather than in lib/misc.h to avoid
67  * circular dependency.
68  */
69 #ifndef likely
70 #define likely(x) __builtin_expect(!!(x), 1)
71 #endif
72 
73 #ifndef unlikely
74 #define unlikely(x) __builtin_expect(!!(x), 0)
75 #endif
76 
80 struct m0_panic_ctx {
85  const char *pc_expr;
87  const char *pc_func;
89  const char *pc_file;
91  int pc_lineno;
97  const char *pc_fmt;
98 };
99 
106 void m0_panic(const struct m0_panic_ctx *ctx, ...)
107  __attribute__((noreturn));
108 
116 M0_INTERNAL void m0_panic_only(const struct m0_panic_ctx *ctx, ...)
117  __attribute__((noreturn));
118 
119 M0_INTERNAL void m0_arch_panic(const struct m0_panic_ctx *ctx, va_list ap)
120  __attribute__((noreturn));
121 
122 void m0_backtrace(void);
123 M0_INTERNAL void m0_arch_backtrace(void);
124 
134 __attribute__ ((format (printf, 1, 2))) static inline void
135 printf_check(const char *fmt, ...)
136 {}
137 
146 #define M0_ASSERT__INIT(msg, fmt, ...) \
147  static const struct m0_panic_ctx __pctx = { \
148  msg, __func__, __FILE__, __LINE__, fmt \
149  }; \
150  printf_check(fmt, ##__VA_ARGS__); \
151  m0_assert_intercept()
152 
159 #define M0_ASSERT_INFO(cond, fmt, ...) \
160 ({ \
161  M0_ASSERT__INIT(#cond, fmt, ##__VA_ARGS__); \
162  (M0_ASSERT_OFF || likely(cond) ? \
163  (void)0 : m0_panic(&__pctx, ##__VA_ARGS__)); \
164 })
165 
167 #define M0_IMPOSSIBLE(fmt, ...) \
168 ({ \
169  M0_ASSERT__INIT("Impossible", "Impossible happened! " fmt, \
170  ##__VA_ARGS__); \
171  m0_panic(&__pctx, ##__VA_ARGS__); \
172 })
173 
185 static inline void m0_assert_intercept(void) {;}
186 
192 #define M0_ASSERT(cond) M0_ASSERT_INFO((cond), NULL)
193 
199 #define M0_ASSERT_EX(cond) \
200 ({ \
201  if (M0_ASSERT_EX_ON) \
202  M0_ASSERT(cond); \
203 })
204 
208 #define M0_ASSERT_INFO_EX(cond, fmt, ...) \
209 ({ \
210  if (M0_ASSERT_EX_ON) \
211  M0_ASSERT_INFO((cond), (fmt), ##__VA_ARGS__); \
212 })
213 
220 #define M0_PRE(cond) M0_ASSERT(cond)
221 
222 #define M0_PRE_EX(cond) M0_ASSERT_EX(cond)
223 
230 #define M0_POST(cond) M0_ASSERT(cond)
231 
232 #define M0_POST_EX(cond) M0_ASSERT_EX(cond)
233 
237 #define M0_INVARIANT_EX(cond) M0_ASSERT_EX(cond)
238 
245 #define M0_CHECK_EX(cond) (!M0_ASSERT_EX_ON || (cond))
246 
254 #define M0_CASSERT(cond) do { switch (1) {case 0: case !!(cond): ;} } while (0)
255 
268 #if defined (__cplusplus) && __cplusplus >= 201103L
269 # define M0_BASSERT(cond) static_assert((cond), #cond)
270 #elif defined (M0_GCC_VERSION) && M0_GCC_VERSION >= 4006
271 # define M0_BASSERT(cond) _Static_assert((cond), #cond)
272 #else
273 # define M0_BASSERT(cond) extern char __static_assertion[(cond) ? 1 : -1]
274 #endif
275 
279 M0_EXTERN const char *m0_failed_condition;
280 
286 M0_INTERNAL void m0__assertion_hook(void);
287 
311 #define _0C(exp) \
312 ({ \
313  bool __exp = (exp); \
314  if (!M0_ASSERT_OFF) { \
315  if (__exp) { \
316  m0_failed_condition = NULL; \
317  } else { \
318  if (m0_failed_condition == NULL) \
319  m0_failed_condition = #exp; \
320  m0__assertion_hook(); \
321  } \
322  } \
323  __exp; \
324 })
325 
336 M0_INTERNAL void m0_debugger_invoke(void);
337 
340 /* __MOTR_LIB_ASSERT_H__ */
341 #endif
342 
343 /*
344  * Local variables:
345  * c-indentation-style: "K&R"
346  * c-basic-offset: 8
347  * tab-width: 8
348  * fill-column: 80
349  * scroll-step: 1
350  * End:
351  */
void m0_backtrace(void)
Definition: assert.c:72
const char * pc_fmt
Definition: assert.h:97
void m0_panic(const struct m0_panic_ctx *ctx,...)
Definition: assert.c:40
M0_INTERNAL const char * m0_failed_condition
Definition: misc.c:224
__attribute__((format(printf, 1, 2))) static inline void printf_check(const char *fmt
M0_INTERNAL void m0_panic_only(const struct m0_panic_ctx *ctx,...)
Definition: assert.c:63
M0_INTERNAL void m0__assertion_hook(void)
Definition: assert.c:78
const char * pc_func
Definition: assert.h:87
M0_INTERNAL void m0_debugger_invoke(void)
Definition: kassert.c:67
int pc_lineno
Definition: assert.h:91
M0_INTERNAL void m0_arch_backtrace(void)
Definition: kassert.c:40
char * fmt(const char *format,...) __attribute__((format(printf
const char * pc_expr
Definition: assert.h:85
format
Definition: hist.py:128
M0_INTERNAL void m0_arch_panic(const struct m0_panic_ctx *ctx, va_list ap) __attribute__((noreturn))
Definition: kassert.c:45
Definition: nucleus.c:42
const char * pc_file
Definition: assert.h:89