|
|
Debugging Services
18.1 Overview
This chapter defines several functions that can be used to help debug and verify UDI drivers and perform internal consistency checking. Contrary to conventions common in many legacy driver models, UDI does not allow a driver to directly invoke a system abort or reset; the UDI environment has the capability, if it desires, to detect a malfunctioning driver and kill or cease to use that driver without affecting the integrity of the rest of the system.
18.2 Debugging Service Calls
In this section, UDI defines one function for debugging (udi_debug_break) and one function for internal consistency checking (udi_assert). These represent the limit of the driver's ability to explicitly cause system-level exceptions, and the handling of these exceptions is dependent on the implementation and current execution mode of the environment under which the driver is running. It is still possible for the driver to perform architectural code violations (e.g. dereference a null pointer) but it is legitimate for the environment to intercept these violations and handle them by killing the driver rather than allowing a system crash as conventionally occurs.
NAME udi_assert
Perform driver internal consistency check
#include <udi.h>void udi_assert ( udi_boolean_t expr );ARGUMENTS expr expression to evaluate for truthfulness
DESCRIPTION The udi_assert function is used by the driver to perform an internal consistency check. The supplied expression expr is evaluated and if the result is false, the consistency check is interpreted as having failed. A failed consistency check indicates an unrecoverable condition within the driver and the UDI environment should take steps to kill the driver or mark it as not-executable. A failed assertion is tantamount to a suicide request on the part of the driver but not for the system as a whole.
The actual handling of an assertion failure is left to the environment implementation. It may be that a particular environment even has multiple execution modes (e.g. free vs. checked) where the failed assertions have different results depending on the mode.
While it is not actually guaranteed that udi_assert will not return to the driver if expr is false, it is expected that drivers will be coded as if that were the case.
As an esoteric note, an environment may choose not to directly handle the udi_assert call simply by returning to the calling code regardless of the success or failure of the evaluated expression. Although the results are indeterminate (and it is likely that the system will subsequently crash as a result of an ignored assertion) the environment implementation has chosen this as a valid outcome of a failed assertion. This is a very subtle environment implementation issue that should not affect driver code; as noted above, driver writers should write their code under the assumption that a failed udi_assert call will not return.
NAME udi_debug_break
Request a debug breakpoint at the current location
#include <udi.h>void udi_debug_break ( udi_init_context_t *init_context, const char *message );ARGUMENTS init_context is the initial context supplied to the driver on the primary region's management channel.
message is a string used to indicate the cause of the debug break.
DESCRIPTION The udi_debug_break function is used for driver debugging purposes. In a debug configuration, calling this routine indicates that a system debugger, if present and available, should be entered at the current time for developer debugging operations.
The init_context argument is used to identify which driver region is issuing the breakpoint. This allows environments to selectively set breakpoints for specific regions as identified by their init_context values..
The implementation of this function is environment dependent and the actions taken may be defined by an operational mode of that UDI environment.
Example An example implementation of the udi_debug_break utility might distinguish between a debug and a non-debug environment, where the former is identified for driver development and the latter is typically the production environment.
In debugging mode, the message string would be output to the debug console and the debugger is entered in the context of the thread that called this function. The operator can then perform various debugging operations and then resume normal execution, which will cause this function to return to the caller for continued execution of UDI driver code.
In a non-debugging mode, the environment may completely ignore this request and simply return immediately to the UDI driver code.
NAME udi_debug_printf
Output a debugging message
#include <udi.h>void udi_debug_printf ( const char *format, ... );ARGUMENTS format is the format string, which controls the formatting of the output string, as described for udi_snprintf.
... are the remaining arguments, which provide the values used for the formatting codes.
description The udi_debug_printf function is intended for use in driver debugging, as a simplified alternative to the pair of udi_snprintf and udi_trace_write, in cases where the output is not needed in production environments. It is expected that udi_debug_printf calls would typically not appear in a (compiled) production driver.
Where required by this or other UDI specifications to trace or log events, drivers must use udi_trace_write or udi_log_write instead of udi_debug_printf, since udi_debug_printf may be a no-op in some environments. Use of udi_debug_printf may impair driver or system performance.
Environments may choose to ignore any or all calls to udi_debug_printf. Some environments may have different operational modes (e.g. debug mode vs. non-debug mode) that treat udi_debug_printf differently. Environments intended to facilitate driver debugging should include at least an option to enable output from udi_debug_printf calls. All environments must at least provide the udi_debug_printf function, even if it does nothing.
Output from udi_debug_printf, if any, will be sent to an environment implementation-defined device, file, or application. Newline (`\n') characters in the format string or any string or character arguments will be translated to an appropriate end of line character(s); other control characters must not be used. Output from each call to udi_debug_printf may be truncated to 99 bytes of text. Note that if the output is truncated, any terminating newline character may have been discarded.