427 lines
16 KiB
C
427 lines
16 KiB
C
/* **********************************************************
|
|
* Copyright 2004 - 2009 VMware, Inc. All rights reserved.
|
|
* **********************************************************/
|
|
|
|
/*
|
|
* @VMKAPIMOD_LICENSE@
|
|
*/
|
|
|
|
/*
|
|
******************************************************************************
|
|
* Assertions */ /**
|
|
*
|
|
* \addtogroup Core
|
|
* @{
|
|
*
|
|
* \defgroup Assert System Panic and Assertions
|
|
* @{
|
|
******************************************************************************
|
|
*/
|
|
|
|
#ifndef _VMKAPI_ASSERT_H_
|
|
#define _VMKAPI_ASSERT_H_
|
|
|
|
/** \cond never */
|
|
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
|
|
#error This vmkapi file should never be included directly but only via vmkapi.h
|
|
#endif
|
|
/** \endcond never */
|
|
|
|
#include <stdarg.h>
|
|
|
|
#if defined(VMK_BUILDING_FOR_KERNEL_MODE)
|
|
|
|
/*
|
|
******************************************************************************
|
|
* vmk_vPanic -- */ /**
|
|
*
|
|
* \brief Indicate that an unrecoverable condition was discovered
|
|
*
|
|
* A module indicates with this function that it discovered an unrecoverable
|
|
* condition. Depending on the system state the VMKernel might initiate a system
|
|
* panic or forcefully disable and unload the module. The caller is guaranteed
|
|
* that no code from the module referenced by moduleID will be executed after a
|
|
* call to this function.
|
|
*
|
|
* \printformatstringdoc
|
|
* \note This function will not return.
|
|
*
|
|
* \param[in] moduleID ModuleID of the panicking module
|
|
* \param[in] fmt Error string in printf format
|
|
* \param[in] ap Additional parameters for the error string
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
void vmk_vPanic(vmk_ModuleID moduleID,
|
|
const char *fmt,
|
|
va_list ap);
|
|
|
|
/*
|
|
******************************************************************************
|
|
* vmk_PanicWithModuleID -- */ /**
|
|
*
|
|
* \brief Indicate that an unrecoverable condition was discovered
|
|
*
|
|
* A module indicates with this function that it discovered an unrecoverable
|
|
* condition. Depending on the system state the VMKernel might initiate a system
|
|
* panic or forcefully disable and unload the module. The caller is guaranteed
|
|
* that no code from the module referenced by moduleID will be executed after a
|
|
* call to this function.
|
|
*
|
|
* \printformatstringdoc
|
|
* \note This function will not return.
|
|
*
|
|
* \param[in] moduleID ModuleID of the panicking module
|
|
* \param[in] fmt Error string in printf format
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
void
|
|
vmk_PanicWithModuleID(vmk_ModuleID moduleID,
|
|
const char *fmt,
|
|
...)
|
|
VMK_ATTRIBUTE_PRINTF(2,3);
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* vmk_Panic -- */ /**
|
|
*
|
|
* \brief Convenience wrapper around vmk_PanicWithModuleID for module local
|
|
* panic calls.
|
|
*
|
|
* \printformatstringdoc
|
|
* \note This function will not return.
|
|
*
|
|
* \param[in] _fmt Error string in printf format
|
|
* \param[in] _args Arguments to the error string
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define vmk_Panic(_fmt, _args...) \
|
|
do { \
|
|
vmk_PanicWithModuleID(vmk_ModuleCurrentID, _fmt, ## _args); \
|
|
} while(0)
|
|
|
|
#else
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* Panic -- */ /**
|
|
*
|
|
* \brief User-provided Panic function that should log the error string
|
|
* in printf format to the application's standard logging mechanism,
|
|
* potentially including additional diagnostic info, such as a stack
|
|
* trace. Panic must not return and it must terminate the application.
|
|
*
|
|
* \printformatstringdoc
|
|
* \note This function must not return and the implementation has to be
|
|
* provided by the user of the vmkapi headers.
|
|
*
|
|
* \param[in] fmt Error string in printf format, followed by arguments
|
|
* to the error string.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
extern void Panic(const char *fmt, ...) VMK_ATTRIBUTE_PRINTF(1, 2);
|
|
|
|
#define vmk_Panic(_fmt, _args...) \
|
|
do { \
|
|
Panic(_fmt, ## _args); \
|
|
} while(0)
|
|
|
|
#endif /* VMK_BUILDING_FOR_KERNEL_MODE */
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_PANIC -- */ /**
|
|
*
|
|
* \brief Helper for VMK_ASSERT_BUG. Panics with the passed message during an
|
|
* assertion failure. If _fmt_ is empty, the stringified version of
|
|
* _cond_ is used as the message.
|
|
*
|
|
* \note Compilation will fail if _fmt_ is not a string constant.
|
|
*
|
|
* \param[in] _cond_ Expression checked in VMK_ASSERT_PANIC.
|
|
* \param[in] _fmt_ Format string constant.
|
|
* \param[in] ... Optional arguments specified by _fmt_.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_PANIC(_cond_,_fmt_,...) \
|
|
do { \
|
|
if (*(_fmt_) == '\0') { \
|
|
vmk_Panic("Failed at %s:%d -- VMK_ASSERT(%s)", \
|
|
__FILE__, __LINE__, #_cond_); \
|
|
} else { \
|
|
vmk_Panic("Failed at %s:%d -- " _fmt_, \
|
|
__FILE__, __LINE__, ## __VA_ARGS__); \
|
|
} \
|
|
} while(0)
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_BUG -- */ /**
|
|
*
|
|
* \brief Panics the system if a runtime expression evalutes to false
|
|
* regardless of debug build status. If optional parameters are
|
|
* passed, those are used to print the panic message instead of
|
|
* the stringified version of the checked expression.
|
|
*
|
|
* \note Compilation will fail if the first variadic argument is not
|
|
* a string constant.
|
|
*
|
|
* \param[in] _cond_ Expression to check.
|
|
* \param[in] ... Optional format string constant followed by arguments
|
|
* that will form a more informative message that just
|
|
* printing the stringified form of the checked
|
|
* expression.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_BUG(_cond_,...) \
|
|
do { \
|
|
if (VMK_UNLIKELY(!(_cond_))) { \
|
|
VMK_ASSERT_PANIC(_cond_, "" __VA_ARGS__); \
|
|
/* Ensure that we don't lose warnings in condition */ \
|
|
if (0) { if (_cond_) {;} } (void)0; \
|
|
} \
|
|
} while(0)
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT -- */ /**
|
|
*
|
|
* \brief Panics the system if a runtime expression evalutes to false
|
|
* only in debug builds. If optional parameters are passed
|
|
* those are used to print the panic message instead of the
|
|
* stringified version of the checked expression.
|
|
*
|
|
* \note Compilation will fail if the first variadic argument is not
|
|
* a string constant.
|
|
*
|
|
* \param[in] _cond_ Expression to check.
|
|
* \param[in] ... Optional format string constant followed by arguments
|
|
* that will form a more informative message that just
|
|
* printing the stringified form of the checked
|
|
* expression.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#if defined(VMX86_DEBUG)
|
|
#define VMK_ASSERT(_cond_,...) VMK_ASSERT_BUG(_cond_, ## __VA_ARGS__)
|
|
#else
|
|
#define VMK_ASSERT(_cond_,...)
|
|
#endif
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_OP -- */ /**
|
|
*
|
|
* \brief Internal helper. Asserts _a_ _op_ _b_.
|
|
*
|
|
* \param[in] _a_ First comparand.
|
|
* \param[in] _b_ Second comparand.
|
|
* \param[in] _op_ Operation to compare with.
|
|
* \param[in] _opname_ Operation name for pretty printing.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_OP(_a_, _b_, _op_, _opname_) \
|
|
VMK_ASSERT((_a_) _op_ (_b_), \
|
|
"VMK_ASSERT_" \
|
|
VMK_STRINGIFY(_opname_) \
|
|
"(" \
|
|
VMK_STRINGIFY(_a_) \
|
|
"(0x%lx), " \
|
|
VMK_STRINGIFY(_b_) \
|
|
"(0x%lx))", \
|
|
(vmk_uint64) (_a_), (vmk_uint64) (_b_))
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_EQ -- */ /**
|
|
*
|
|
* \brief Asserts _a_ == _b_.
|
|
*
|
|
* \param[in] _a_ First comparand.
|
|
* \param[in] _b_ Second comparand.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_EQ(_a_, _b_) VMK_ASSERT_OP(_a_, _b_, ==, EQ)
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_NE -- */ /**
|
|
*
|
|
* \brief Asserts _a_ != _b_.
|
|
*
|
|
* \param[in] _a_ First comparand.
|
|
* \param[in] _b_ Second comparand.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_NE(_a_, _b_) VMK_ASSERT_OP(_a_, _b_, !=, NE)
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_GE -- */ /**
|
|
*
|
|
* \brief Asserts _a_ >= _b_.
|
|
*
|
|
* \param[in] _a_ First comparand.
|
|
* \param[in] _b_ Second comparand.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_GE(_a_, _b_) VMK_ASSERT_OP(_a_, _b_, >=, GE)
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_LE -- */ /**
|
|
*
|
|
* \brief Asserts _a_ <= _b_.
|
|
*
|
|
* \param[in] _a_ First comparand.
|
|
* \param[in] _b_ Second comparand.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_LE(_a_, _b_) VMK_ASSERT_OP(_a_, _b_, <=, LE)
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_GT -- */ /**
|
|
*
|
|
* \brief Asserts _a_ > _b_.
|
|
*
|
|
* \param[in] _a_ First comparand.
|
|
* \param[in] _b_ Second comparand.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_GT(_a_, _b_) VMK_ASSERT_OP(_a_, _b_, >, GT)
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_LT -- */ /**
|
|
*
|
|
* \brief Asserts _a_ < _b_.
|
|
*
|
|
* \param[in] _a_ First comparand.
|
|
* \param[in] _b_ Second comparand.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_LT(_a_, _b_) VMK_ASSERT_OP(_a_, _b_, <, LT)
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_NOT_NULL -- */ /**
|
|
*
|
|
* \brief Asserts _a_ != NULL.
|
|
*
|
|
* \param[in] _a_ Value to compare to NULL.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_NOT_NULL(_a_) VMK_ASSERT((_a_) != NULL)
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_NULL -- */ /**
|
|
*
|
|
* \brief Asserts _a_ == NULL.
|
|
*
|
|
* \param[in] _a_ Value to compare to NULL.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_NULL(_a_) \
|
|
VMK_ASSERT((_a_) == NULL, \
|
|
"VMK_ASSERT_NULL(" \
|
|
VMK_STRINGIFY(_a_) \
|
|
"(%p))", \
|
|
(_a_))
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_ON_COMPILE -- */ /**
|
|
*
|
|
* \ingroup Assert
|
|
* \brief Fail compilation if a condition does not hold true
|
|
*
|
|
* \note This macro must be used inside the context of a function.
|
|
*
|
|
* \param[in] _cond_ Expression to check.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_ON_COMPILE(_cond_) \
|
|
do { \
|
|
switch(0) { \
|
|
case 0: \
|
|
case (_cond_): \
|
|
; \
|
|
} \
|
|
} while(0) \
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* VMK_ASSERT_LIST -- */ /**
|
|
*
|
|
* \brief To put a VMK_ASSERT_ON_COMPILE() outside a function, wrap it in
|
|
* VMK_ASSERT_LIST(). The first parameter must be unique in each .c
|
|
* file where it appears
|
|
*
|
|
* \par Example usage with VMK_ASSERT_ON_COMPILE:
|
|
*
|
|
* \code
|
|
* VMK_ASSERT_LIST(fs_assertions,
|
|
* VMK_ASSERT_ON_COMPILE(sizeof(fs_diskLock) == 128);
|
|
* VMK_ASSERT_ON_COMPILE(sizeof(fs_LockRes) == DISK_BLK_SIZE);
|
|
* )
|
|
* \endcode
|
|
*
|
|
* \param[in] _name_ Unique name of the list of assertions.
|
|
* \param[in] _assertions_ Individual assert-on-compile statements.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#define VMK_ASSERT_LIST(_name_, _assertions_) \
|
|
static inline void _name_(void) { \
|
|
_assertions_ \
|
|
}
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* VMK_NOT_REACHED -- */ /**
|
|
*
|
|
* \ingroup Assert
|
|
* \brief Panic if code reaches this call
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
#define VMK_NOT_REACHED() \
|
|
vmk_Panic("Failed at %s:%d -- NOT REACHED", __FILE__, __LINE__)
|
|
|
|
#endif /* _VMKAPI_ASSERT_H_ */
|
|
/** @} */
|
|
/** @} */
|