|
|
Time Management
UDI supports two types of time-related services: Timer Services, which allow driver callback routines to be called at specific times; and Timestamp Services, which allow drivers to measure elapsed time. These are described in more detail in separate sections below.
14.1 Timer Services
14.1.1 Timed Delays
UDI timer services provide a set of operations that can be used to schedule future events for handling. The UDI timer services are very similar to legacy timer services found in most operating systems and provide a mechanism to schedule the call of a driver's timeout routine at some point in the future (relative to the current time). UDI timers may be of either the one-shot variety or may be invoked as repeating timers where the timeout routine will be called repeatedly until cancelled.
UDI timer services shall be implemented with the expectation that the normal operation of most timers is to start the timer to accompany a request and then cancel the timer when the request is successfully handled by the device. Timer startup and cancellation shall therefore be implemented by the environment with minimal overhead to allow their use in the datapath in this manner.
14.1.2 Timer Context
The UDI timer services are performed using a control block structure (e.g., udi_cb_t) to provide a context to the timer operations. The control block provides context information about the original request that can be used in the timeout routine. However, there are cases where the timer is not directly related to any current request and a specific control block is needed to manage the timeout operation. One example of this is a watchdog timer routine where the timeout routine is called periodically to check the general health of the device independent of any current requests. To handle these general timeout situations, a control block will be needed. Any available control block may be used so long as it is not needed for any other purpose; in practice, however, this usually means that a new control block will have to be allocated with udi_cb_alloc. In this case, a control block index associated with udi_gcb_init can be used to allocate a generic control block.
Control blocks are a finite system resource. It is a responsibility of a device driver to allocate, track and return control blocks to the UDI environment in a responsible manner.
NAME udi_time_t
Time value structure
#include <udi.h>typedef struct {
udi_ubit32_t seconds;
udi_ubit32_t nanoseconds;
} udi_time_t;MEMBERS seconds is the number of seconds of time.
nanoseconds is the number of additional nanoseconds of time. Thus nanoseconds ranges from zero to one less than one thousand million (10^9) nanoseconds.
DESCRIPTION The udi_time_t structure is used to specify a timeout interval for use with the UDI Timer Services or an elapsed time interval returned by UDI Timestamp Services. The fields in this structure allow very precise specification of time values relative to the current time; the udi_limits_t values should be consulted to determine the actual granularity of the environment's timers, as all specified udi_time_t values will be rounded up to integral multiples of the minimum system timer resolution.
This structure is not used to represent absolute ("wall-clock") times. UDI provides no facility to determine absolute time.
NAME udi_timer_start
Start a callback timer
#include <udi.h>void udi_timer_start ( udi_timer_expired_call_t *callback, udi_cb_t *gcb, udi_time_t interval ); typedef void udi_timer_expired_call_t ( udi_cb_t *gcb );ARGUMENTS callback, gcb are standard arguments described in the "Asynchronous Service Calls" section of "Calling Sequence and Naming Conventions".
interval is the desired minimum interval that should elapse between the time the event is initiated with udi_timer_start and the time callback is called. The actual interval will depend on system activity, platform implementation (e.g. clock interrupt interval), timer resolution (min_timer_res), and the availability of processor resources. Under normal system activity the actual interval will be at least as long as the specified interval and not usually more than interval plus min_timer_res.
DESCRIPTION udi_timer_start schedules a delayed callback according to the parameters specified. The callback routine will be called at some time in the future, as specified by interval.
As with other control block operations, the ownership of the control block passes from the driver to the environment until such time as the callback is invoked and the control block is passed back. Re-using the specified control block for this or any other request before it has been returned to the driver via the callback routine is illegal. This may require the driver to obtain another control block by calling udi_cb_alloc in order to be able to dedicate it to this purpose.
A udi_timer_start request may be cancelled at any time by calling the udi_timer_cancel routine with the original control block pointer.
WARNINGS Control block usage must follow the rules described in the "Asynchronous Service Calls" section of "Calling Sequence and Naming Conventions".
REFERENCES udi_time_t, udi_limits_t, udi_cb_alloc, udi_timer_cancel
NAME udi_timer_start_repeating
Start a repeating timer
#include <udi.h>void udi_timer_start_repeating ( udi_timer_tick_call_t *callback, udi_cb_t *gcb, udi_time_t interval ); typedef void udi_timer_tick_call_t ( void *context, udi_ubit32_t nmissed );ARGUMENTS callback, gcb are standard arguments described in the "Asynchronous Service Calls" section of "Calling Sequence and Naming Conventions".
interval is the repeating period for this timer (see udi_timer_start). For udi_timer_start_repeating, interval must be greater than zero.
context is the context pointer from the original control block, gcb.
nmissed is the number of timeout callbacks missed.
DESCRIPTION udi_timer_start_repeating behaves like udi_timer_start except that the callback routine is called repeatedly at each successive occurrence of interval. Repeated callbacks are timed relative to the original starting time, rather than the last callback time.
Each time the specified interval timeout period has elapsed (within system timer resolution capability) the callback function is called. If the callback routine is currently scheduled or active or the environment otherwise is unable to call the callback on schedule, the environment will increment an internal counter representing the number of missed timeout calls for a particular timeout control block. This missed timeout count is passed to the callback function as the nmissed argument; this indicator allows the driver to determine if it has missed callbacks and take appropriate action. The nmissed value will only reflect missed callbacks since the last delivered callback. After a missed callback, the next callback may be delivered any time between the scheduled time of the missed callback and the normally scheduled time for the next callback.
The repeating timer can be stopped by calling udi_timer_cancel from either the callback timeout routine or from other code within the region that started the timer with the original control block.
Unlike other callback functions, udi_timer_tick_call_t does not pass the control block back to the driver, since it remains busy until the repeating timer is cancelled with udi_timer_cancel.
REFERENCES udi_time_t, udi_limits_t, udi_cb_alloc, udi_timer_cancel
NAME udi_timer_cancel
Cancel a pending timer
#include <udi.h>void udi_timer_cancel ( udi_cb_t *gcb );ARGUMENTS gcb is a pointer to a control block that was passed to a prior udi_timer_start or udi_timer_start_repeating service call.
DESCRIPTION Any timer service request with a pending callback can be canceled by this call. The control block must be the same one specified when the service was requested, and must be active (i.e. the callback has not yet been called).
Once udi_timer_cancel has returned, the original callback routine is guaranteed not to be called. Ownership of the control block is transferred back to the requestor, and the control block is available for reuse.
WARNINGS udi_timer_cancel must be called from the region that owned the control block at the time of the original request. It cannot be used to cancel a pending request in another region.
A driver must keep track of its in-progress requests to avoid canceling a different request than intended. A good rule of thumb is that udi_timer_cancel must not be used to cancel a request without first checking to see if the corresponding callback has been called.
If a driver issues a udi_timer_cancel for a control block that is not active the driver is in error. See the "Driver Faults/Recovery" section of "Execution Model" for an explanation of how the environment may react to this driver error.
REFERENCES udi_timer_start, udi_timer_start_repeating, udi_cancel
14.2 Timestamp Services
Timestamp services allow drivers to measure elapsed time. This is accomplished by taking snapshots, or timestamps, of the current time, using udi_time_current() and comparing multiple timestamps with udi_time_between() or udi_time_since(). Timestamps are represented using the self-contained opaque type, udi_timestamp_t, defined in Section 9.6.2.1, "Timestamp Type".
NAME udi_time_current
Return indication of the current relative time
#include <udi.h>udi_timestamp_t udi_time_current ( void );DESCRIPTION udi_time_current returns the current time (relative to some arbitrary starting point), in implementation-specific units. The system time resolution can be determined from the min_curtime_res field in the udi_limits_t structure.
No UDI services are provided to directly convert a udi_timestamp_t value to standard units, such as in a udi_time_t. Instead, timestamp values can be compared using udi_time_since or udi_time_between. udi_timestamp_t is a self-contained opaque type, and is therefore not transferable between regions.
In many environments, timestamp values are only useful for accurate comparisons for a limited amount of time. That is, when compared to another timestamp value they may appear to be more recent than the actual time at which they were obtained, since underlying time counters may wrap around. In all environments, udi_timestamp_t values are guaranteed to be useful for at least 24 hours.
RETURN VALUES The current time stamp is returned to the caller.
WARNINGS There are no guaranteed "invalid" values for udi_timestamp_t. In order to represent an invalid or uninitialized timestamp value, an external flag must be used.
Drivers must not assume that repeated calls to udi_time_current without returning from the driver will ever return different values; environments may choose to update the underlying time value only between calls into the driver. Delays must be implemented with timer services not timestamp services.
REFERENCES udi_time_t, udi_limits_t, udi_time_since, udi_time_between
See also Section 9.6.2.1, "Timestamp Type".
NAME udi_time_between
Return time interval between two points
#include <udi.h>udi_time_t udi_time_between ( udi_timestamp_t start_time, udi_timestamp_t end_time );ARGUMENTS start_time is a timestamp value marking the starting point of the interval.
end_time is a timestamp value marking the ending point of the interval.
DESCRIPTION udi_time_between returns the time delta between two previously recorded times, in start_time and end_time. The previously recorded times must have been obtained via udi_time_current.
start_time must reflect a time that occurred no later than end_time.
The system time resolution can be determined from the min_curtime_res field in the udi_limits_t structure.
RETURN VALUES The time interval, in seconds and nanoseconds, is returned to the caller.
REFERENCES udi_time_t, udi_limits_t, udi_time_current, udi_time_since
NAME udi_time_since
Return time interval since a starting point
#include <udi.h>udi_time_t udi_time_since ( udi_timestamp_t start_time );ARGUMENTS start_time is a timestamp value marking the starting point of the interval.
DESCRIPTION udi_time_since returns the time delta between a previously recorded time, in start_time, and the current time. The previously recorded time must have been obtained via udi_time_current.
The system time resolution can be determined from the min_curtime_res field in the udi_limits_t structure.
udi_time_since is equivalent to:
udi_time_between(start_time, udi_time_current())RETURN VALUES The time interval, in seconds and nanoseconds, is returned to the caller.
warnings Drivers must not assume that repeated calls to udi_time_since without returning from the driver will ever return different values; environments may choose to update the underlying time value only between calls into the driver. Delays must be implemented with timer services not timestamp services.