|
|
lbolt is a signed int that counts the number of clock ticks since the system was booted. Drivers that use traditional driver interfaces use lbolt to keep track of short delays or timeouts.
In earlier operating systems, drivers accessed lbolt values directly. lbolt becomes negative after the system has been up long enough for lbolt to wrap. For example, with a 32-bit clock_t value and a HZ value of 100 ticks-per-second, lbolt becomes negative after approximately 248 days; see ``CLOCK_MAX''. Code that depends on lbolt not becoming negative or that compares old and new values of lbolt may produce unintended results after the system has been up for 248 days.
Beginning with DDI 8 and ODDI 5, drivers can use the TICKS(D3) macros to access lbolt values and avoid the problems traditionally associated with manipulating the lbolt value either directly or, for DDI drivers, with the drv_getparm(D3) function. The TICKS macros are:
start_time = TICKS();As another example, the following code determines when at least one half second has elapsed:/* do something */
if (TICKS_SINCE(start_time) >= MAX_TICKS)
start_time = TICKS();Note the use of the Hz variable to represent the number of ticks in a second./* do something */
if (TICKS_SINCE(start_time) >= Hz/2)
/* action to take */
Drivers written for DDI versions prior to version 8 and ODDI versions prior to version 5 must deal more directly with lbolt operations. DDI drivers use the drv_getparm(D3) function with the LBOLT parameter whereas ODDI drivers access lbolt directly, but similar issues are involved.
An example of the incorrect use of lbolt is the test
Incorrect use of lbolt
if (lbolt >= (start_time + MAX_TICKS) /* INCORRECT use of lbolt */This is intended to determine whether or not MAX_TICKS ticks have passed since time start_time, but fails if start_time and (start_time+MAX_TICKS) are positive while lbolt has wrapped and is negative.
To avoid these problems, compare the lbolt values by subtracting one value from the other, as in:
if (lbolt - start_time >= MAX_TICKS) /* CORRECT use of lbolt */The subtraction works whether lbolt is negative or positive. Both lbolt and start_time must be declared as signed integers. Otherwise, the code will compile and appear to work correctly, but will have problems after the system is up for 248 days.
DDI drivers should never access lbolt directly, but should use the LBOLT flag to the drv_getparm(D3) function. Use the drv_hztousec(D3) and drv_usectohz(D3) functions to convert between clock ticks and microseconds.
The proper way to access lbolt through the drv_getparm( ) function is illustrated below:
Accessing lbolt for DDI versions prior to version 8
{ clock_t start_time, end_time;drv_getparm(LBOLT, &start_time);
/* do something */
drv_getparm(LBOLT, &end_time); duration_in_usec = drv_hztousec(end_time - start_time); }
Note the final conversion to microseconds, which are implementation-independent units. The driver does not actually know how long a tick is.
ODDI drivers access the lbolt variable directly. The proper way to use lbolt on SCO OpenServer 5 systems is illustrated below. This code determines when at least ten clock ticks have elapsed.
Accessing lbolt for ODDI drivers on SCO OpenServer 5
start_time = lboltIt is important to test behavior near the 248- and 497-day boundaries, when lbolt wraps from positive to negative and then from negative to positive. Such tests can be done by directly setting lbolt to values a few minutes before each rollover point using the kernel debugger. For SCO OpenServer Release 5.0.4 and later, the user-level scodb(ADM) facility can be used in a script to repeatedly reset lbolt to various boundary values./* do something */
if (lbolt - start_time >= 10) {
/* action to take */ }
UDI provides timer facilities that hide all these issues from the driver writer. This is necessary to handle the variations in system time units and the implementation difficulties associated with direct access to lbolt. UDI driver writers can access the system timer resolution using the udi_timestamp_t object, but are not allowed to access times directly in ``native'' units.
Chapter 15 of the UDI Specification
is dedicated to time management and discusses
the functions used to replace lbolt code in a driver:
udi_timer_start( ),
udi_timer_start_repeating( ),
udi_timer_cancel( ),
udi_timer_current( ),
udi_time_between( ),
and
udi_time_since( ).