diff options
author | Patrick Williams <iawillia@us.ibm.com> | 2011-06-24 10:13:59 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2011-07-06 13:32:14 -0500 |
commit | 9ada6b493e33fe43057b03897d57f2ad931d219f (patch) | |
tree | bbf89ebdb16bf9b1fe2b466979d610835e8e58fb /src/include | |
parent | 6c77e26e9454c6753d989f33430c4e361f6ff003 (diff) | |
download | talos-hostboot-9ada6b493e33fe43057b03897d57f2ad931d219f.tar.gz talos-hostboot-9ada6b493e33fe43057b03897d57f2ad931d219f.zip |
Improve assert handling and options.
- Allow a custom assert trace as an optional parameter.
- Call a trace function instead of printk for most cases.
- Provide a critical library assert (for syslibs, trace, etc.)
- Provide a kassert function for kernel code.
Change-Id: If24d57d0832a587258503b3fd0046c21da3712b5
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/159
Tested-by: Jenkins Server
Reviewed-by: Andrew J. Geissler <andrewg@us.ibm.com>
Reviewed-by: CAMVAN T. NGUYEN <ctnguyen@us.ibm.com>
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/assert.h | 150 | ||||
-rw-r--r-- | src/include/builtins.h | 12 |
2 files changed, 152 insertions, 10 deletions
diff --git a/src/include/assert.h b/src/include/assert.h index 13888bee8..a8f3fb664 100644 --- a/src/include/assert.h +++ b/src/include/assert.h @@ -1,27 +1,159 @@ -#include <builtins.h> - +/** @file assert.h + * @brief Define the interfaces for the standard 'assert' macros. + * + * There are four different assert types provided now: + * Standard assert behavior: + * assert(foo) + * + * Standard assert behavior with a custom trace message: + * assert(foo, "This is a trace %d", 1234) + * + * Critical assert, which should only be used by system libraries or + * code paths which cannot use trace or error logging: + * crit_assert(foo) + * + * Kernel assert: + * kassert(foo) + * + * Most code should use the standard asserts. Kernel code must use kassert + * exclusively. Usage of the critical assert should be limited to system + * library code (/src/lib, /src/sys) or init service, trace and error log. + */ #ifndef _ASSERT_H #define _ASSERT_H +#include <builtins.h> + +#ifdef __HOSTBOOT_MODULE // Only allow traced assert in module code. +#include <trace/interface.H> +namespace TRACE { extern trace_desc_t* g_assertTraceBuffer; }; +#endif + #ifdef __cplusplus extern "C" { #endif +/** @enum AssertBehavior + * @brief Types of assert behavior used by the internal __assert function. + */ +enum AssertBehavior +{ + /** Standard assert, custom trace already done. */ + ASSERT_TRACE_DONE, + /** Standard assert, no custom trace. */ + ASSERT_TRACE_NOTDONE, + /** Critical / System library assert. */ + ASSERT_CRITICAL, + /** Kernel-level assert. */ + ASSERT_KERNEL, +}; + +/** @fn __assert + * @brief Internal function utilized by assert macros to commonize handling. + * + * @param[in] i_assertb - Internal enumeration used by macros to communicate + * desired behavior. + * @param[in] i_line - Line number at which the assert macro was called. + * + * Current Behaviors: + * User-space application - A trace is created, either a custom one + * provided by the caller or a common one + * determined by the trace callback hook, and + * the asserting task is ended. + * + * Critical library - A printk is performed, similar in structure to the + * traces, and the user task is ended. + * + * Kernel - A printk is performed and a while(1) loop is entered to cease + * user-space dispatching. + */ NO_RETURN -void __assert(bool expr, const char *exprStr, const char *file, int line); +void __assert(AssertBehavior i_assertb, int i_line); + +#ifdef __HOSTBOOT_MODULE // Only allow traced assert in module code. -#define assert(expr) \ +// Macro tricks to determine if there is a custom string. +#define __ASSERT_HAS_TRACE_(_1, _2, ...) _2 +#define __ASSERT_HAS_TRACE(...) __ASSERT_HAS_TRACE_(0, ##__VA_ARGS__, 0) + +/** + * @brief Macro to do the custom trace if one is provided. + * + * This results in larger code size of the caller to call the trace routines + * but may provide additional debug information. + * + * The "code" here will be compiled down to nothing or a single trace call by + * the optimizer. Search for "Constant Folding" for compiler background. + */ +#define __ASSERT_DO_TRACE(expr, ...) { \ + int __assert_unused_var = 0; \ + __assert_unused_var += (__ASSERT_HAS_TRACE(__VA_ARGS__) ? \ + TRACFCOMP(TRACE::g_assertTraceBuffer, \ + "Assertion [ " #expr " ] failed; " __VA_ARGS__),1 \ + : 0); \ + } + +/** + * @brief Standard assert macro. + * + * Verfies condition, calls custom trace if provided, and calls internal + * __assert function for remainder of common assert behavior. + */ +#define assert(expr,...) \ {\ - if (!(expr))\ + if (unlikely(!(expr)))\ {\ - __assert((expr), #expr, __FILE__, __LINE__);\ + __ASSERT_DO_TRACE(expr, __VA_ARGS__); \ + __assert((__ASSERT_HAS_TRACE(__VA_ARGS__) ? \ + ASSERT_TRACE_DONE : ASSERT_TRACE_NOTDONE),\ + __LINE__);\ }\ -}\ +} + +#else // Only allow kernel assert in non-module code. -#ifdef NDEBUG +/** + * @brief Kernel assert macro. + * + * Verifies condition and calls __assert function for common behavior. + */ +#define kassert(expr) \ +{\ + if (unlikely(!(expr)))\ + {\ + __assert(ASSERT_KERNEL, __LINE__);\ + }\ +} + +#endif // ifdef __HOSTBOOT_MODULE + +// Allow critical assert anywhere. +/** + * @brief Critical assert macro. + * + * Verifies condition and calls __assert function for common behavior. + */ +#define crit_assert(expr) \ +{\ + if (unlikely(!(expr)))\ + {\ + __assert(ASSERT_CRITICAL, __LINE__);\ + }\ +} + + + +#ifdef NDEBUG // Empty macro definitions for when NDEBUG is defined. +#ifdef MODULE #undef assert -#define assert(expr) { } +#define assert(expr,...) { } +#else +#undef kassert +#define kassert(expr) { } +#endif +#undef crit_assert +#define crit_assert(expr,...) { } #endif #ifdef __cplusplus diff --git a/src/include/builtins.h b/src/include/builtins.h index 07b185697..54b7dc768 100644 --- a/src/include/builtins.h +++ b/src/include/builtins.h @@ -45,6 +45,16 @@ extern "C" #define PACKED __attribute__((packed)) /** + * Compiler hint for branch conditions. "condition is likely to be true" + */ +#define likely(expr) __builtin_expect((expr),1) + +/** + * Compiler hint for branch conditions. "condition is likely to be false" + */ +#define unlikely(expr) __builtin_expect((expr),0) + +/** * Get the value of the link register * * @return the value of the link register @@ -52,7 +62,7 @@ extern "C" ALWAYS_INLINE static inline void *linkRegister() { - return __builtin_return_address(1); + return __builtin_return_address(0); } /** |