Data Structures

Let us now turn our attention to how low-resolution timers are implemented. You have already seen that processing is initiated by run_local_timers, but before this function is discussed, some prerequisites in the form of data structures must be introduced.

Timers are organized on lists, and the following data structure represents a timer on a list: <timer.h>

struct timer_list {

struct list_head entry; unsigned long expires;

void (*function)(unsigned long); unsigned long data;

struct tvec_t_base_s *base;

As usual, a doubly linked list is used to link registered timers with each other. entry is the list head. The other structure items have the following meaning:

□ function saves a pointer to the callback function invoked upon time-out.

□ data is an argument for the callback function.

□ expires specifies the time, in jiffies, at which the timer expires.

□ base is a pointer to a base element in which the timers are sorted on their expiry time (discussed in more detail shortly). There is a base element for each processor of the system; consequently, the CPU upon which the timer runs can be determined using base.

The macro DEFINE_TIMER(_name, _function, _expires, _data) is provided to declare a static timer_list instance.

Times are given in two formats in the kernel — as offsets or as absolute values. Both make use of jiffies. While offsets are used when a new timer is installed, all kernel data structures use absolute values because they can easily be compared with the current jiffies time. The expires element of timer_list also uses absolute times and not offsets.

Because programmers tend to think in seconds rather than in HZ units when defining time intervals, the kernel provides a matching data structure plus the option of converting into jiffies (and, of course, vice versa):

struct timeval {

suseconds_t tv_usec; /* microseconds */

The elements are self-explanatory. The complete time interval is calculated by adding the specified second and microsecond values. The timeval_to_jiffies and jiffies_to_timeval functions are used to convert between this representation and a jiffies value. These functions are implemented in <timer.h>.

Another possibility to specify times includes nanoseconds instead of microseconds:

struct timespec {

time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */

Again auxiliary functions convert back and forth between jiffies and timespecs: timespec_to_jiffies and jiffies_to_timespec.

Continue reading here: Mode of Operation

Was this article helpful?

0 0