aboutsummaryrefslogtreecommitdiff
path: root/include/os/freebsd/spl/sys/debug.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/os/freebsd/spl/sys/debug.h')
-rw-r--r--include/os/freebsd/spl/sys/debug.h194
1 files changed, 171 insertions, 23 deletions
diff --git a/include/os/freebsd/spl/sys/debug.h b/include/os/freebsd/spl/sys/debug.h
index 86fad18e17d2..f041dde34fc8 100644
--- a/include/os/freebsd/spl/sys/debug.h
+++ b/include/os/freebsd/spl/sys/debug.h
@@ -39,12 +39,14 @@
* ASSERT3U() - Assert unsigned X OP Y is true, if not panic.
* ASSERT3P() - Assert pointer X OP Y is true, if not panic.
* ASSERT0() - Assert value is zero, if not panic.
+ * ASSERT0P() - Assert pointer is null, if not panic.
* VERIFY() - Verify X is true, if not panic.
* VERIFY3B() - Verify boolean X OP Y is true, if not panic.
* VERIFY3S() - Verify signed X OP Y is true, if not panic.
* VERIFY3U() - Verify unsigned X OP Y is true, if not panic.
* VERIFY3P() - Verify pointer X OP Y is true, if not panic.
* VERIFY0() - Verify value is zero, if not panic.
+ * VERIFY0P() - Verify pointer is null, if not panic.
*/
#ifndef _SPL_DEBUG_H
@@ -54,23 +56,63 @@
/*
* Common DEBUG functionality.
*/
-int spl_panic(const char *file, const char *func, int line,
+#ifdef __FreeBSD__
+#include <linux/compiler.h>
+#endif
+
+#ifndef __printflike
+#define __printflike(a, b) __printf(a, b)
+#endif
+
+#ifndef __maybe_unused
+#define __maybe_unused __attribute__((unused))
+#endif
+
+/*
+ * Without this, we see warnings from objtool during normal Linux builds when
+ * the kernel is built with CONFIG_STACK_VALIDATION=y:
+ *
+ * warning: objtool: tsd_create() falls through to next function __list_add()
+ * warning: objtool: .text: unexpected end of section
+ *
+ * Until the toolchain stops doing this, we must only define this attribute on
+ * spl_panic() when doing static analysis.
+ */
+#if defined(__COVERITY__) || defined(__clang_analyzer__)
+__attribute__((__noreturn__))
+#endif
+extern void spl_panic(const char *file, const char *func, int line,
const char *fmt, ...);
-void spl_dumpstack(void);
+extern void spl_dumpstack(void);
+
+static inline int
+spl_assert(const char *buf, const char *file, const char *func, int line)
+{
+ spl_panic(file, func, line, "%s", buf);
+ return (0);
+}
#ifndef expect
#define expect(expr, value) (__builtin_expect((expr), (value)))
#endif
+#ifndef __linux__
#define likely(expr) expect((expr) != 0, 1)
#define unlikely(expr) expect((expr) != 0, 0)
+#endif
#define PANIC(fmt, a...) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, fmt, ## a)
#define VERIFY(cond) \
(void) (unlikely(!(cond)) && \
- spl_panic(__FILE__, __FUNCTION__, __LINE__, \
- "%s", "VERIFY(" #cond ") failed\n"))
+ spl_assert("VERIFY(" #cond ") failed\n", \
+ __FILE__, __FUNCTION__, __LINE__))
+
+#define VERIFYF(cond, str, ...) do { \
+ if (unlikely(!cond)) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY(" #cond ") failed " str "\n", __VA_ARGS__);\
+ } while (0)
#define VERIFY3B(LEFT, OP, RIGHT) do { \
const boolean_t _verify3_left = (boolean_t)(LEFT); \
@@ -79,8 +121,8 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%d " #OP " %d)\n", \
- (boolean_t)(_verify3_left), \
- (boolean_t)(_verify3_right)); \
+ (boolean_t)_verify3_left, \
+ (boolean_t)_verify3_right); \
} while (0)
#define VERIFY3S(LEFT, OP, RIGHT) do { \
@@ -90,8 +132,8 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%lld " #OP " %lld)\n", \
- (long long) (_verify3_left), \
- (long long) (_verify3_right)); \
+ (long long)_verify3_left, \
+ (long long)_verify3_right); \
} while (0)
#define VERIFY3U(LEFT, OP, RIGHT) do { \
@@ -101,8 +143,8 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%llu " #OP " %llu)\n", \
- (unsigned long long) (_verify3_left), \
- (unsigned long long) (_verify3_right)); \
+ (unsigned long long)_verify3_left, \
+ (unsigned long long)_verify3_right); \
} while (0)
#define VERIFY3P(LEFT, OP, RIGHT) do { \
@@ -112,20 +154,116 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%px " #OP " %px)\n", \
- (void *) (_verify3_left), \
- (void *) (_verify3_right)); \
+ (void *)_verify3_left, \
+ (void *)_verify3_right); \
} while (0)
#define VERIFY0(RIGHT) do { \
+ const int64_t _verify0_right = (int64_t)(RIGHT); \
+ if (unlikely(!(0 == _verify0_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY0(" #RIGHT ") " \
+ "failed (0 == %lld)\n", \
+ (long long)_verify0_right); \
+ } while (0)
+
+#define VERIFY0P(RIGHT) do { \
+ const uintptr_t _verify0_right = (uintptr_t)(RIGHT); \
+ if (unlikely(!(0 == _verify0_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY0P(" #RIGHT ") " \
+ "failed (NULL == %px)\n", \
+ (void *)_verify0_right); \
+ } while (0)
+
+/*
+ * Note that you should not put any operations you want to always happen
+ * in the print section for ASSERTs unless you only want them to run on
+ * debug builds!
+ * e.g. ASSERT3UF(2, <, 3, "%s", foo(x)), foo(x) won't run on non-debug
+ * builds.
+ */
+
+#define VERIFY3BF(LEFT, OP, RIGHT, STR, ...) do { \
+ const boolean_t _verify3_left = (boolean_t)(LEFT); \
+ const boolean_t _verify3_right = (boolean_t)(RIGHT); \
+ if (unlikely(!(_verify3_left OP _verify3_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
+ "failed (%d " #OP " %d) " STR "\n", \
+ (boolean_t)(_verify3_left), \
+ (boolean_t)(_verify3_right), \
+ __VA_ARGS__); \
+ } while (0)
+
+#define VERIFY3SF(LEFT, OP, RIGHT, STR, ...) do { \
+ const int64_t _verify3_left = (int64_t)(LEFT); \
+ const int64_t _verify3_right = (int64_t)(RIGHT); \
+ if (unlikely(!(_verify3_left OP _verify3_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
+ "failed (%lld " #OP " %lld) " STR "\n", \
+ (long long)(_verify3_left), \
+ (long long)(_verify3_right), \
+ __VA_ARGS); \
+ } while (0)
+
+#define VERIFY3UF(LEFT, OP, RIGHT, STR, ...) do { \
+ const uint64_t _verify3_left = (uint64_t)(LEFT); \
+ const uint64_t _verify3_right = (uint64_t)(RIGHT); \
+ if (unlikely(!(_verify3_left OP _verify3_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
+ "failed (%llu " #OP " %llu) " STR "\n", \
+ (unsigned long long)(_verify3_left), \
+ (unsigned long long)(_verify3_right), \
+ __VA_ARGS); \
+ } while (0)
+
+#define VERIFY3PF(LEFT, OP, RIGHT, STR, ...) do { \
+ const uintptr_t _verify3_left = (uintptr_t)(LEFT); \
+ const uintptr_t _verify3_right = (uintptr_t)(RIGHT); \
+ if (unlikely(!(_verify3_left OP _verify3_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
+ "failed (%px " #OP " %px) " STR "\n", \
+ (void *) (_verify3_left), \
+ (void *) (_verify3_right), \
+ __VA_ARGS__); \
+ } while (0)
+
+#define VERIFY0PF(RIGHT, STR, ...) do { \
+ const uintptr_t _verify3_left = (uintptr_t)(0); \
+ const uintptr_t _verify3_right = (uintptr_t)(RIGHT); \
+ if (unlikely(!(_verify3_left == _verify3_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY0(0 == " #RIGHT ") " \
+ "failed (0 == %px) " STR "\n", \
+ (long long) (_verify3_right), \
+ __VA_ARGS__); \
+ } while (0)
+
+#define VERIFY0F(RIGHT, STR, ...) do { \
const int64_t _verify3_left = (int64_t)(0); \
const int64_t _verify3_right = (int64_t)(RIGHT); \
if (unlikely(!(_verify3_left == _verify3_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
- "VERIFY3(0 == " #RIGHT ") " \
- "failed (0 == %lld)\n", \
- (long long) (_verify3_right)); \
+ "VERIFY0(0 == " #RIGHT ") " \
+ "failed (0 == %lld) " STR "\n", \
+ (long long) (_verify3_right), \
+ __VA_ARGS__); \
} while (0)
+#define VERIFY_IMPLY(A, B) \
+ ((void)(likely((!(A)) || (B)) || \
+ spl_assert("(" #A ") implies (" #B ")", \
+ __FILE__, __FUNCTION__, __LINE__)))
+
+#define VERIFY_EQUIV(A, B) \
+ ((void)(likely(!!(A) == !!(B)) || \
+ spl_assert("(" #A ") is equivalent to (" #B ")", \
+ __FILE__, __FUNCTION__, __LINE__)))
+
/*
* Debugging disabled (--disable-debug)
*/
@@ -141,6 +279,14 @@ void spl_dumpstack(void);
#define ASSERT3P(x, y, z) \
((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
#define ASSERT0(x) ((void) sizeof ((uintptr_t)(x)))
+#define ASSERT0P(x) ((void) sizeof ((uintptr_t)(x)))
+#define ASSERT3BF(x, y, z, str, ...) ASSERT3B(x, y, z)
+#define ASSERT3SF(x, y, z, str, ...) ASSERT3S(x, y, z)
+#define ASSERT3UF(x, y, z, str, ...) ASSERT3U(x, y, z)
+#define ASSERT3PF(x, y, z, str, ...) ASSERT3P(x, y, z)
+#define ASSERT0PF(x, str, ...) ASSERT0P(x)
+#define ASSERT0F(x, str, ...) ASSERT0(x)
+#define ASSERTF(x, str, ...) ASSERT(x)
#define IMPLY(A, B) \
((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B)))
#define EQUIV(A, B) \
@@ -156,15 +302,17 @@ void spl_dumpstack(void);
#define ASSERT3U VERIFY3U
#define ASSERT3P VERIFY3P
#define ASSERT0 VERIFY0
+#define ASSERT0P VERIFY0P
+#define ASSERT3BF VERIFY3BF
+#define ASSERT3SF VERIFY3SF
+#define ASSERT3UF VERIFY3UF
+#define ASSERT3PF VERIFY3PF
+#define ASSERT0PF VERIFY0PF
+#define ASSERT0F VERIFY0F
+#define ASSERTF VERIFYF
#define ASSERT VERIFY
-#define IMPLY(A, B) \
- ((void)(likely((!(A)) || (B)) || \
- spl_panic(__FILE__, __FUNCTION__, __LINE__, \
- "(" #A ") implies (" #B ")")))
-#define EQUIV(A, B) \
- ((void)(likely(!!(A) == !!(B)) || \
- spl_panic(__FILE__, __FUNCTION__, __LINE__, \
- "(" #A ") is equivalent to (" #B ")")))
+#define IMPLY VERIFY_IMPLY
+#define EQUIV VERIFY_EQUIV
#endif /* NDEBUG */