tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: KASSERTMSG fix



On 08.09.2011 19:38, Joerg Sonnenberger wrote:
> On Thu, Sep 08, 2011 at 06:41:54PM +0200, Jean-Yves Migeon wrote:
>> On 08.09.2011 14:27, Joerg Sonnenberger wrote:
>>> There is no reason to allocate a string, just reserve e.g. 160 Bytes or
>>> so and use snprintf to that. But yes, the current usage is suboptimal.
>>
>> So let's make it a little bit more helpful: see panicstr.diff.
> 
> I would change one minor aspect: set panicstr to fmt before calling
> va_start etc, to give at least some basic information in case that fails
> for any reason. Otherwise I think that should go in, it already improves
> the status quo. We can discuss the rest after that.

Bringing back the thing again; quoting a previous mail from me:

> Summary about my discussion regarding KASSERTMSG(): in its current form
> it cannot append the msg passed as argument to it to the panic format
> string, which makes it rather impractical: we fail to log the file,
> line, expression that triggered the assertion and worse, it does not
> conform to its description in KASSERT(9).
> 
> It would be very practical to append "msg" to the panic string while
> keeping its usefulness: "msg" can specify a format string with optional
> arguments (helpful when you are interested in more information that the
> assertion alone).
> 
> Joerg proposed to introduce a panic_verbose(9) function which is a
> panic(9) function enhanced with additional arguments:
> 
> panic_verbose(__FILE__, __LINE__, #e, fmt, ##__VA_ARGS__)
> 
> This needs to (re)write the string parsing parts of panic(9) to cope
> with the additional arguments. I can't simply add a wrapper around
> panic(9) with a scratch string for that, concurrent callers could
> completely thrash it (due to preemptions etc).
> 
> I am not really convinced that we should touch panic(9) to provide
> KASSERTMSG() functionality. IMHO we cannot predict future uses and
> adapting the prototype each time is cumbersome, especially as
> KASSERTMSG(...) isn't widely used throughout the kernel.
> 
> Having two format strings in the prototype is a possibility (pointed by
> Mouse). va_* plays is something I'd like to keep to the kprintf(9)
> functions though. This would need a specific format specifier for va_list
> also.
> 
> So I am back with the __VA_ARGS__ tricks; with the attached patch and
> all the KASSERT call sites fixed, the ALL kernel size is actually
> smaller... [by about 20k]

I am attaching the patch I wrote for the proposal above (note attaching
the patch for call sites, it's worthless for now)

Comments are welcomed, I'd like to improve the KASSERTMSG(...) macro a
bit. Currently, it's just a mere alias for an if + panic(9).

-- 
Jean-Yves Migeon
jeanyves.migeon%free.fr@localhost
Index: sys/lib/libkern/libkern.h
===================================================================
RCS file: /cvsroot/src/sys/lib/libkern/libkern.h,v
retrieving revision 1.99
diff -u -p -r1.99 libkern.h
--- sys/lib/libkern/libkern.h   1 Sep 2011 22:35:17 -0000       1.99
+++ sys/lib/libkern/libkern.h   16 Sep 2011 22:44:22 -0000
@@ -37,6 +37,7 @@
 #include <sys/types.h>
 #include <sys/inttypes.h>
 #include <sys/null.h>
+#include <sys/systm.h>
 
 #ifndef LIBKERN_INLINE
 #define LIBKERN_INLINE static __inline
@@ -174,15 +175,17 @@ tolower(int ch)
 
 #define        __NULL_STMT             do { } while (/* CONSTCOND */ 0)
 
+#define ASSERTSTR "kernel %sassertion \"%s\" failed: file \"%s\", line %d "
+
 #ifdef NDEBUG                                          /* tradition! */
 #define        assert(e)       ((void)0)
 #else
 #ifdef __STDC__
 #define        assert(e)       (__predict_true((e)) ? (void)0 :                
    \
-                           kern_assert("", __FILE__, __LINE__, #e))
+                           panic(ASSERTSTR, "", #e, __FILE__, __LINE__))
 #else
 #define        assert(e)       (__predict_true((e)) ? (void)0 :                
    \
-                           kern_assert("", __FILE__, __LINE__, "e"))
+                           panic(ASSERTSTR, "", "e", __FILE__, __LINE__))
 #endif
 #endif
 
@@ -197,46 +200,50 @@ tolower(int ch)
 #ifndef DIAGNOSTIC
 #define _DIAGASSERT(a) (void)0
 #ifdef lint
-#define        KASSERTMSG(e, msg)      /* NOTHING */
+#define        KASSERTMSG(e, msg, ...) /* NOTHING */
 #define        KASSERT(e)              /* NOTHING */
 #else /* !lint */
-#define        KASSERTMSG(e, msg)      ((void)0)
+#define        KASSERTMSG(e, msg, ...) ((void)0)
 #define        KASSERT(e)              ((void)0)
 #endif /* !lint */
 #else /* DIAGNOSTIC */
 #define _DIAGASSERT(a) assert(a)
-#define        KASSERTMSG(e, msg) do {         \
-       if (__predict_false(!(e)))      \
-               panic msg;              \
-       } while (/*CONSTCOND*/ 0)
+#define        KASSERTMSG(e, msg, ...)         \
+                       (__predict_true((e)) ? (void)0 :                    \
+                           panic(ASSERTSTR msg, "diagnostic ", #e,         \
+                               __FILE__, __LINE__, ## __VA_ARGS__))
 #ifdef __STDC__
 #define        KASSERT(e)      (__predict_true((e)) ? (void)0 :                
    \
-                           kern_assert("diagnostic ", __FILE__, __LINE__, #e))
+                           panic(ASSERTSTR, "diagnostic ", #e,             \
+                               __FILE__, __LINE__))
 #else
 #define        KASSERT(e)      (__predict_true((e)) ? (void)0 :                
    \
-                           kern_assert("diagnostic ", __FILE__, __LINE__,"e"))
+                           panic(ASSERTSTR, "diagnostic ", "e",            \
+                               __FILE__, __LINE__))
 #endif
 #endif
 
 #ifndef DEBUG
 #ifdef lint
-#define        KDASSERTMSG(e,msg)      /* NOTHING */
+#define        KDASSERTMSG(e,msg, ...) /* NOTHING */
 #define        KDASSERT(e)             /* NOTHING */
 #else /* lint */
-#define        KDASSERTMSG(e,msg)      ((void)0)
+#define        KDASSERTMSG(e,msg, ...) ((void)0)
 #define        KDASSERT(e)             ((void)0)
 #endif /* lint */
 #else
-#define        KDASSERTMSG(e, msg) do {        \
-       if (__predict_false(!(e)))      \
-               panic msg;              \
-       } while (/*CONSTCOND*/ 0)
+#define        KDASSERTMSG(e, msg, ...)        \
+                       (__predict_true((e)) ? (void)0 :                    \
+                           panic(ASSERTSTR msg, "debugging ", #e,          \
+                               __FILE__, __LINE__, ## __VA_ARGS__))
 #ifdef __STDC__
 #define        KDASSERT(e)     (__predict_true((e)) ? (void)0 :                
    \
-                           kern_assert("debugging ", __FILE__, __LINE__, #e))
+                           panic(ASSERTSTR, "debugging ", #e,              \
+                               __FILE__, __LINE__))
 #else
 #define        KDASSERT(e)     (__predict_true((e)) ? (void)0 :                
    \
-                           kern_assert("debugging ", __FILE__, __LINE__, "e"))
+                           panic(ASSERTSTR, "debugging ", "e",             \
+                               __FILE__, __LINE__))
 #endif
 #endif
 /*


Home | Main Index | Thread Index | Old Index