Print this page
Test of DTrace assert probes
@@ -38,28 +38,59 @@
#include <sys/isa_defs.h>
#include <sys/types.h>
#include <sys/note.h>
+#ifdef KEBE
+#include <sys/sdt.h>
+#endif /* KEBE */
+
#ifdef __cplusplus
extern "C" {
#endif
/*
* ASSERT(ex) causes a panic or debugger entry if expression ex is not
* true. ASSERT() is included only for debugging, and is a no-op in
* production kernels. VERIFY(ex), on the other hand, behaves like
* ASSERT and is evaluated on both debug and non-debug kernels.
+ *
+ * KEBE SAYS if "KEBE" is defined on a non-DEBUG kernel, the ASSERT() will
+ * form an SDT probe of the form sdt:module:function:assert-<lineno>, with
+ * probe arguments:
+ *
+ * arg0 -> file name
+ * arg1 -> line number
+ * arg2 -> EX
*/
+#ifdef KEBE
+/* XXX KEBE HOPES that __LINE__ evaluates the same, but isn't sure. */
+#define ASSERTDTSTRBASE(x, y) x ## y
+#define ASSERTDTSTR(x, y) ASSERTDTSTRBASE(x, y)
+#define ASSERTDT(EX) do { \
+ extern void ASSERTDTSTR(__dtrace_probe_assert__, __LINE__)(uintptr_t, \
+ uintptr_t, uintptr_t); \
+ if (!(EX)) \
+ ASSERTDTSTR(__dtrace_probe_assert__, __LINE__) \
+ ((uintptr_t)__FILE__, \
+ (uintptr_t)__LINE__, (uintptr_t)#EX); \
+_NOTE(CONSTCOND) } while (0)
+#endif /* KEBE */
+
+
extern int assfail(const char *, const char *, int);
#define VERIFY(EX) ((void)((EX) || assfail(#EX, __FILE__, __LINE__)))
#if DEBUG
#define ASSERT(EX) ((void)((EX) || assfail(#EX, __FILE__, __LINE__)))
#else
+#ifdef KEBE
+#define ASSERT(EX) ASSERTDT(EX)
+#else
#define ASSERT(x) ((void)0)
-#endif
+#endif /* KEBE */
+#endif /* DEBUG */
/*
* Assertion variants sensitive to the compilation data model
*/
#if defined(_LP64)
@@ -97,10 +128,39 @@
* for unsigned, and ASSERT3P() is for pointers. The VERIFY3*() macros
* have the same relationship as above.
*/
extern void assfail3(const char *, uintmax_t, const char *, uintmax_t,
const char *, int);
+
+#ifdef KEBE
+/*
+ * KEBE SAYS, for the sdt:module:function:assert3-<lineno> will have more
+ * probe arguments:
+ *
+ * arg0 -> file name
+ * arg1 -> line number
+ * arg2 -> EX
+ * arg3 -> "left" boolean
+ * arg4 -> "OP" string
+ * arg5 -> "right" boolean
+ */
+#define KEBE3_IMPL(LEFT, OP, RIGHT, TYPE) do { \
+ extern void ASSERTDTSTR(__dtrace_probe_assert3__, __LINE__)( \
+ uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, \
+ uintptr_t); \
+ const TYPE __left = (TYPE)(LEFT); \
+ const TYPE __right = (TYPE)(RIGHT); \
+ if (!(__left OP __right)) \
+ ASSERTDTSTR(__dtrace_probe_assert3__, __LINE__) \
+ ((uintptr_t)__FILE__, \
+ (uintptr_t)__LINE__, \
+ (uintptr_t)(#LEFT " " #OP " " #RIGHT), \
+ (uintptr_t)__left, (uintptr_t)#OP, \
+ (uintptr_t)__right); \
+_NOTE(CONSTCOND) } while (0)
+#endif /* KEBE */
+
#define VERIFY3_IMPL(LEFT, OP, RIGHT, TYPE) do { \
const TYPE __left = (TYPE)(LEFT); \
const TYPE __right = (TYPE)(RIGHT); \
if (!(__left OP __right)) \
assfail3(#LEFT " " #OP " " #RIGHT, \
@@ -117,14 +177,21 @@
#define ASSERT3S(x, y, z) VERIFY3_IMPL(x, y, z, int64_t)
#define ASSERT3U(x, y, z) VERIFY3_IMPL(x, y, z, uint64_t)
#define ASSERT3P(x, y, z) VERIFY3_IMPL(x, y, z, uintptr_t)
#define ASSERT0(x) VERIFY3_IMPL(x, ==, 0, uintmax_t)
#else
+#ifdef KEBE
+#define ASSERT3S(x, y, z) KEBE3_IMPL(x, y, z, int64_t)
+#define ASSERT3U(x, y, z) KEBE3_IMPL(x, y, z, uint64_t)
+#define ASSERT3P(x, y, z) KEBE3_IMPL(x, y, z, uintptr_t)
+#define ASSERT0(x) KEBE3_IMPL(x, ==, 0, uintmax_t)
+#else
#define ASSERT3S(x, y, z) ((void)0)
#define ASSERT3U(x, y, z) ((void)0)
#define ASSERT3P(x, y, z) ((void)0)
#define ASSERT0(x) ((void)0)
+#endif /* KEBE */
#endif
/*
* Compile-time assertion. The condition 'x' must be constant.
*/