text: /*
   * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
   * Distributed under the terms of the MIT License.
   */
  #ifndef _KERNEL_DEBUG_PARANOIA_H
  #define _KERNEL_DEBUG_PARANOIA_H
  
  #include <sys/cdefs.h>
  
  #include <SupportDefs.h>
  
  #include "paranoia_config.h"
  
  
  // How to use: Include the header only from source files. Set
  // COMPONENT_PARANOIA_LEVEL before. Use the macros defined below and the
  // ParanoiaChecker class.
  
  // paranoia levels
  #define PARANOIA_NAIVE		0	/* don't do any checks */
  #define PARANOIA_SUSPICIOUS	1	/* do some checks */
  #define PARANOIA_OBSESSIVE	2	/* do a lot of checks */
  #define PARANOIA_INSANE		3	/* do all checks, also very expensive ones */
  
  // mode for set_paranoia_check()
  enum paranoia_set_check_mode {
  	PARANOIA_DONT_FAIL,			// succeed, if check for address exists or not
  	PARANOIA_FAIL_IF_EXISTS,	// fail, if check for address already exists
  	PARANOIA_FAIL_IF_MISSING	// fail, if check for address doesn't exist yet
  };
  
  
  __BEGIN_DECLS
  
  #if ENABLE_PARANOIA_CHECKS
  
  status_t	create_paranoia_check_set(const void* object,
  				const char* description);
  status_t	delete_paranoia_check_set(const void* object);
  status_t	run_paranoia_checks(const void* object);
  
  status_t	set_paranoia_check(const void* object, const void* address,
  				size_t size, paranoia_set_check_mode mode);
  status_t	remove_paranoia_check(const void* object, const void* address,
  				size_t size);
  
  #endif	// ENABLE_PARANOIA_CHECKS
  
  void		debug_paranoia_init();
  
  __END_DECLS
  
  
  #if ENABLE_PARANOIA_CHECKS && COMPONENT_PARANOIA_LEVEL
  #	define PARANOIA_ONLY(x)	x
  #	define PARANOIA_ONLY_LEVEL(level, x)				\
  		if ((level) <= (COMPONENT_PARANOIA_LEVEL)) {	\
  			x;											\
  		}
  #else
  #	define PARANOIA_ONLY(x)
  #	define PARANOIA_ONLY_LEVEL(level, x)
  #endif
  
  #define	CREATE_PARANOIA_CHECK_SET(object, description)	\
  			PARANOIA_ONLY(create_paranoia_check_set((object), (description)))
  #define	DELETE_PARANOIA_CHECK_SET(object)	\
  			PARANOIA_ONLY(delete_paranoia_check_set((object)))
  #define	RUN_PARANOIA_CHECKS(object)	\
  			PARANOIA_ONLY(run_paranoia_checks((object)))
  
  #define	ADD_PARANOIA_CHECK(level, object, address, size)		\
  			PARANOIA_ONLY_LEVEL((level),						\
  				set_paranoia_check((object), (address), (size), \
  					PARANOIA_FAIL_IF_EXISTS))
  #define	UPDATE_PARANOIA_CHECK(level, object, address, size)		\
  			PARANOIA_ONLY_LEVEL((level),						\
  				set_paranoia_check((object), (address), (size), \
  					PARANOIA_FAIL_IF_MISSING))
  #define	SET_PARANOIA_CHECK(level, object, address, size)		\
  			PARANOIA_ONLY_LEVEL((level),						\
  				set_paranoia_check((object), (address), (size), \
  					PARANOIA_DONT_FAIL))
  #define	REMOVE_PARANOIA_CHECK(level, object, address, size)		\
  			PARANOIA_ONLY_LEVEL((level),						\
  				remove_paranoia_check((object), (address), (size)))
  
  
  #ifdef __cplusplus
  
  class ParanoiaChecker {
  public:
  	inline ParanoiaChecker(const void* object)
  	{
  		PARANOIA_ONLY(fObject = object);
  		RUN_PARANOIA_CHECKS(fObject);
  	}
  
  	inline ~ParanoiaChecker()
  	{
  		PARANOIA_ONLY(
  			if (fObject != NULL)
  				RUN_PARANOIA_CHECKS(fObject);
  		)
  	}
  
  	inline void Disable()
  	{
  		PARANOIA_ONLY(fObject = NULL);
  	}
  
  private:
  	PARANOIA_ONLY(
  		const void*	fObject;
  	)
  };
  
  #endif	// __cplusplus
  
  
  #endif	// _KERNEL_DEBUG_PARANOIA_H
  