1 //
2 // Copyright (c) 2008 Travis Geiselbrecht
3 // Copyright 2016 The Fuchsia Authors
4 //
5 // Use of this source code is governed by a MIT-style
6 // license that can be found in the LICENSE file or at
7 // https://opensource.org/licenses/MIT
8 //
9 #pragma once
10 
11 #include <lk/compiler.h>
12 #include <lk/debug.h>
13 
14 // Assert that |x| is true, else panic.
15 //
16 // ASSERT is always enabled and |x| will be evaluated regardless of any build arguments.
17 #define ASSERT(x)                          \
18   do {                                     \
19     if (unlikely(!(x))) {                  \
20       assert_fail(__FILE__, __LINE__, #x); \
21     }                                      \
22   } while (0)
23 
24 // Assert that |x| is true, else panic with the given message.
25 //
26 // ASSERT_MSG is always enabled and |x| will be evaluated regardless of any build arguments.
27 #define ASSERT_MSG(x, msg, msgargs...)                         \
28   do {                                                         \
29     if (unlikely(!(x))) {                                      \
30       assert_fail_msg(__FILE__, __LINE__, #x, msg, ##msgargs); \
31     }                                                          \
32   } while (0)
33 
34 
35 // DEBUG_ASSERT_IMPLEMENTED is intended to be used to conditionalize code that is logically part of
36 // a debug assert. It's useful for performing complex consistency checks that are difficult to work
37 // into a DEBUG_ASSERT statement.
38 #define DEBUG_ASSERT_IMPLEMENTED (LK_DEBUGLEVEL > 1)
39 
40 // Assert that |x| is true, else panic.
41 //
42 // Depending on build arguments, DEBUG_ASSERT may or may not be enabled. When disabled, |x| will not
43 // be evaluated.
44 #define DEBUG_ASSERT(x)                               \
45   do {                                                \
46     if (DEBUG_ASSERT_IMPLEMENTED && unlikely(!(x))) { \
47       assert_fail(__FILE__, __LINE__, #x);            \
48     }                                                 \
49   } while (0)
50 
51 // Assert that |x| is true, else panic with the given message.
52 //
53 // Depending on build arguments, DEBUG_ASSERT_MSG may or may not be enabled. When disabled, |x| will
54 // not be evaluated.
55 #define DEBUG_ASSERT_MSG(x, msg, msgargs...)                   \
56   do {                                                         \
57     if (DEBUG_ASSERT_IMPLEMENTED && unlikely(!(x))) {          \
58       assert_fail_msg(__FILE__, __LINE__, #x, msg, ##msgargs); \
59     }                                                          \
60   } while (0)
61 
62 // implement _COND versions of DEBUG_ASSERT which only emit the body if
63 // DEBUG_ASSERT_IMPLEMENTED is set
64 #if DEBUG_ASSERT_IMPLEMENTED
65 #define DEBUG_ASSERT_COND(x) DEBUG_ASSERT(x)
66 #define DEBUG_ASSERT_MSG_COND(x, msg, msgargs...) DEBUG_ASSERT_MSG(x, msg, msgargs)
67 #else
68 #define DEBUG_ASSERT_COND(x) \
69   do {                       \
70   } while (0)
71 #define DEBUG_ASSERT_MSG_COND(x, msg, msgargs...) \
72   do {                                            \
73   } while (0)
74 #endif
75 
76 // make sure static_assert() is defined, even in C
77 #if !defined(__cplusplus) && !defined(static_assert)
78 #define static_assert(e, msg) _Static_assert(e, msg)
79 #endif
80 
81 // Use DEBUG_ASSERT or ASSERT instead.
82 //
83 // assert() is defined only because third-party code used in the kernel expects it.
84 #define assert(x) DEBUG_ASSERT(x)
85 
86 __BEGIN_CDECLS
87 
88 // The following functions are called when an assert fails.
89 void assert_fail(const char *file, int line, const char *expression) __NO_RETURN __NO_INLINE;
90 void assert_fail_msg(const char *file, int line, const char *expression, const char *fmt,
91                      ...) __PRINTFLIKE(4, 5) __NO_RETURN __NO_INLINE;
92 
93 __END_CDECLS
94